blob: 03334a4ed8d4ba518527354ded1d6de42eb950ad [file] [log] [blame]
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.dev.javac;
import com.google.gwt.dev.jdt.SafeASTVisitor;
import com.google.gwt.dev.util.Name.InternalName;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
/**
* Base class of things that walk methods in a CUD and collect things about
* interesting methods.
*/
public abstract class MethodVisitor {
/**
* Gets a unique name for this method, including its signature.
*/
protected static String getMemberSignature(AbstractMethodDeclaration method) {
String name = String.valueOf(method.selector);
StringBuilder sb = new StringBuilder();
sb.append(name);
sb.append("(");
if (method.arguments != null) {
for (Argument param : method.arguments) {
sb.append(param.binding.type.signature());
}
}
sb.append(")");
return sb.toString();
}
/**
* Collect data about interesting methods in one compilation unit.
*
* @param cud
*/
public void collect(final CompilationUnitDeclaration cud) {
cud.traverse(new SafeASTVisitor() {
@Override
public void endVisit(TypeDeclaration type, ClassScope scope) {
collectMethods(type);
}
@Override
public void endVisit(TypeDeclaration type, CompilationUnitScope scope) {
collectMethods(type);
}
@Override
public void endVisitValid(TypeDeclaration type, BlockScope scope) {
collectMethods(type);
}
}, cud.scope);
}
/**
* Provided by a subclass to return true if this method should be processed.
* This is separate since some extra work is performed in order to call
* {@link #processMethod}.
*
* @param method
* @return true if processMethod should be called on this method
*/
protected abstract boolean interestingMethod(AbstractMethodDeclaration method);
/**
* Provided by a subclass to process a method definition. Methods which have
* no name are not passed to this method, even if {@link #interestingMethod}
* returns true.
*
* @param typeDecl
* @param method
* @param enclosingType
* @param loc
*/
protected abstract void processMethod(TypeDeclaration typeDecl,
AbstractMethodDeclaration method, String enclosingType);
/**
* Collect data about interesting methods on a particular type in a
* compilation unit.
*
* @param cud
* @param typeDecl
*/
private void collectMethods(TypeDeclaration typeDecl) {
AbstractMethodDeclaration[] methods = typeDecl.methods;
if (methods == null) {
return;
}
// Lazy initialize these when an interesting method is actually hit.
String enclosingType = null;
boolean lazyInitialized = false;
for (AbstractMethodDeclaration method : methods) {
if (!interestingMethod(method)) {
continue;
}
if (!lazyInitialized) {
enclosingType = InternalName.toBinaryName(String.valueOf(typeDecl.binding.constantPoolName()));
lazyInitialized = true;
}
processMethod(typeDecl, method, enclosingType);
}
}
}