forked from phoedos/pmd
Improve SymbolTable times further
- Expand hashCode calculation for `MethodNameDeclaration` to avoid collisions when overloading. - Also make sure `builtInMethodDeclaration` provides a complete syntax tree to avoid NPE when calling `hashCode` or `equals`
This commit is contained in:
@ -28,6 +28,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTType;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTTypeParameter;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTTypeParameters;
|
||||
@ -43,6 +45,20 @@ import net.sourceforge.pmd.lang.symboltable.Scope;
|
||||
*/
|
||||
public class ClassScope extends AbstractJavaScope {
|
||||
|
||||
private static final Set<String> PRIMITIVE_TYPES;
|
||||
|
||||
static {
|
||||
PRIMITIVE_TYPES = new HashSet<>();
|
||||
PRIMITIVE_TYPES.add("boolean");
|
||||
PRIMITIVE_TYPES.add("char");
|
||||
PRIMITIVE_TYPES.add("byte");
|
||||
PRIMITIVE_TYPES.add("short");
|
||||
PRIMITIVE_TYPES.add("int");
|
||||
PRIMITIVE_TYPES.add("long");
|
||||
PRIMITIVE_TYPES.add("float");
|
||||
PRIMITIVE_TYPES.add("double");
|
||||
}
|
||||
|
||||
// FIXME - this breaks given sufficiently nested code
|
||||
private static ThreadLocal<Integer> anonymousInnerClassCounter = new ThreadLocal<Integer>() {
|
||||
protected Integer initialValue() {
|
||||
@ -206,7 +222,7 @@ public class ClassScope extends AbstractJavaScope {
|
||||
}
|
||||
}
|
||||
if (isEnum && "valueOf".equals(occurrence.getImage())) {
|
||||
result.add(createBuiltInMethodDeclaration("valueOf", 1));
|
||||
result.add(createBuiltInMethodDeclaration("valueOf", "String"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -253,7 +269,7 @@ public class ClassScope extends AbstractJavaScope {
|
||||
* @param parameterCount the parameter count of the method
|
||||
* @return a method name declaration
|
||||
*/
|
||||
private MethodNameDeclaration createBuiltInMethodDeclaration(final String methodName, final int parameterCount) {
|
||||
private MethodNameDeclaration createBuiltInMethodDeclaration(final String methodName, final String... parameterTypes) {
|
||||
ASTMethodDeclaration methodDeclaration = new ASTMethodDeclaration(JavaParserTreeConstants.JJTMETHODDECLARATION);
|
||||
methodDeclaration.setPublic(true);
|
||||
methodDeclaration.setScope(this);
|
||||
@ -270,7 +286,7 @@ public class ClassScope extends AbstractJavaScope {
|
||||
methodDeclarator.jjtAddChild(formalParameters, 0);
|
||||
formalParameters.jjtSetParent(methodDeclarator);
|
||||
|
||||
for (int i = 0; i < parameterCount; i++) {
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
ASTFormalParameter formalParameter = new ASTFormalParameter(JavaParserTreeConstants.JJTFORMALPARAMETER);
|
||||
formalParameters.jjtAddChild(formalParameter, i);
|
||||
formalParameter.jjtSetParent(formalParameters);
|
||||
@ -282,6 +298,23 @@ public class ClassScope extends AbstractJavaScope {
|
||||
variableDeclaratorId.setImage("arg" + i);
|
||||
formalParameter.jjtAddChild(variableDeclaratorId, 1);
|
||||
variableDeclaratorId.jjtSetParent(formalParameter);
|
||||
|
||||
if (PRIMITIVE_TYPES.contains(parameterTypes[i])) {
|
||||
ASTPrimitiveType primitiveType = new ASTPrimitiveType(JavaParserTreeConstants.JJTPRIMITIVETYPE);
|
||||
primitiveType.setImage(parameterTypes[i]);
|
||||
type.jjtAddChild(primitiveType, 0);
|
||||
primitiveType.jjtSetParent(type);
|
||||
} else {
|
||||
ASTReferenceType referenceType = new ASTReferenceType(JavaParserTreeConstants.JJTREFERENCETYPE);
|
||||
type.jjtAddChild(referenceType, 0);
|
||||
referenceType.jjtSetParent(type);
|
||||
|
||||
// TODO : this could actually be a primitive array...
|
||||
ASTClassOrInterfaceType coiType = new ASTClassOrInterfaceType(JavaParserTreeConstants.JJTCLASSORINTERFACETYPE);
|
||||
coiType.setImage(parameterTypes[i]);
|
||||
referenceType.jjtAddChild(coiType, 0);
|
||||
coiType.jjtSetParent(referenceType);
|
||||
}
|
||||
}
|
||||
|
||||
MethodNameDeclaration mnd = new MethodNameDeclaration(methodDeclarator);
|
||||
|
@ -36,7 +36,7 @@ public class MethodNameDeclaration extends AbstractNameDeclaration {
|
||||
}
|
||||
|
||||
public String getParameterDisplaySignature() {
|
||||
StringBuilder sb = new StringBuilder("(");
|
||||
StringBuilder sb = new StringBuilder("(");
|
||||
ASTFormalParameters params = (ASTFormalParameters) node.jjtGetChild(0);
|
||||
// TODO - this can be optimized - add [0] then ,[n] in a loop.
|
||||
// no need to trim at the end
|
||||
@ -44,7 +44,7 @@ public class MethodNameDeclaration extends AbstractNameDeclaration {
|
||||
ASTFormalParameter p = (ASTFormalParameter) params.jjtGetChild(i);
|
||||
sb.append(p.getTypeNode().getTypeImage());
|
||||
if (p.isVarargs()) {
|
||||
sb.append("...");
|
||||
sb.append("...");
|
||||
}
|
||||
sb.append(',');
|
||||
}
|
||||
@ -82,7 +82,7 @@ public class MethodNameDeclaration extends AbstractNameDeclaration {
|
||||
|
||||
// Compare vararg
|
||||
if (myParam.isVarargs() != otherParam.isVarargs()) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
Node myTypeNode = myParam.getTypeNode().jjtGetChild(0);
|
||||
@ -118,7 +118,24 @@ public class MethodNameDeclaration extends AbstractNameDeclaration {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return node.getImage().hashCode() + ((ASTMethodDeclarator) node).getParameterCount();
|
||||
int hash = node.getImage().hashCode() * 31 + ((ASTMethodDeclarator) node).getParameterCount();
|
||||
|
||||
ASTFormalParameters myParams = (ASTFormalParameters) node.jjtGetChild(0);
|
||||
for (int i = 0; i < ((ASTMethodDeclarator) node).getParameterCount(); i++) {
|
||||
ASTFormalParameter myParam = (ASTFormalParameter) myParams.jjtGetChild(i);
|
||||
Node myTypeNode = myParam.getTypeNode().jjtGetChild(0);
|
||||
|
||||
String myTypeImg;
|
||||
if (myTypeNode instanceof ASTPrimitiveType) {
|
||||
myTypeImg = myTypeNode.getImage();
|
||||
} else {
|
||||
myTypeImg = myTypeNode.jjtGetChild(0).getImage();
|
||||
}
|
||||
|
||||
hash = hash * 31 + myTypeImg.hashCode();
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Reference in New Issue
Block a user