Skip to content

Commit

Permalink
Improve Javac(Method|Type)Binding.getKey() (eclipse-jdt#273)
Browse files Browse the repository at this point in the history
Fixes eclipse-jdt#284

---------

Signed-off-by: David Thompson <davthomp@redhat.com>
Signed-off-by: Rob Stryker <stryker@redhat.com>
Co-authored-by: Rob Stryker <stryker@redhat.com>
  • Loading branch information
datho7561 and Rob Stryker authored Apr 24, 2024
1 parent 36482ef commit d34d8af
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,14 @@ private Optional<Symbol> symbol(JCTree value) {
ITypeBinding resolveType(Type type) {
resolve();
JCTree jcTree = this.converter.domToJavac.get(type);
final java.util.List<TypeSymbol> typeArguments = getTypeArguments(type);
if (jcTree instanceof JCIdent ident && ident.sym instanceof TypeSymbol typeSymbol) {
return new JavacTypeBinding(typeSymbol, this, typeArguments);
return new JavacTypeBinding(ident.type, this);
}
if (jcTree instanceof JCFieldAccess access && access.sym instanceof TypeSymbol typeSymbol) {
return new JavacTypeBinding(typeSymbol, this, typeArguments);
return new JavacTypeBinding(access.type, this);
}
if (jcTree instanceof JCPrimitiveTypeTree primitive) {
return new JavacTypeBinding(primitive.type, this, typeArguments);
return new JavacTypeBinding(primitive.type, this);
}
// return this.flowResult.stream().map(env -> env.enclClass)
// .filter(Objects::nonNull)
Expand All @@ -167,7 +166,7 @@ ITypeBinding resolveType(TypeDeclaration type) {
resolve();
JCTree javacNode = this.converter.domToJavac.get(type);
if (javacNode instanceof JCClassDecl jcClassDecl) {
return new JavacTypeBinding(jcClassDecl.sym, this, null);
return new JavacTypeBinding(jcClassDecl.type, this);
}
return null;
}
Expand All @@ -177,18 +176,18 @@ ITypeBinding resolveType(EnumDeclaration enumDecl) {
resolve();
JCTree javacNode = this.converter.domToJavac.get(enumDecl);
if (javacNode instanceof JCClassDecl jcClassDecl) {
return new JavacTypeBinding(jcClassDecl.sym, this, null);
return new JavacTypeBinding(jcClassDecl.type, this);
}
return null;
}

public IBinding getBinding(final Symbol owner, final java.util.List<TypeSymbol> typeArguments) {
public IBinding getBinding(final Symbol owner, final com.sun.tools.javac.code.Type type) {
if (owner instanceof final PackageSymbol other) {
return new JavacPackageBinding(other, this);
} else if (owner instanceof final TypeSymbol other) {
return new JavacTypeBinding(other, this, typeArguments);
} else if (owner instanceof TypeSymbol) {
return new JavacTypeBinding(type, this);
} else if (owner instanceof final MethodSymbol other) {
return new JavacMethodBinding(other, this, typeArguments);
return new JavacMethodBinding(type.asMethodType(), other, this);
} else if (owner instanceof final VarSymbol other) {
return new JavacVariableBinding(other, this);
}
Expand All @@ -209,15 +208,14 @@ IVariableBinding resolveField(FieldAccess fieldAccess) {
IMethodBinding resolveMethod(MethodInvocation method) {
resolve();
JCTree javacElement = this.converter.domToJavac.get(method);
final java.util.List<TypeSymbol> typeArguments = getTypeArguments(method);
if (javacElement instanceof JCMethodInvocation javacMethodInvocation) {
javacElement = javacMethodInvocation.getMethodSelect();
}
if (javacElement instanceof JCIdent ident && ident.sym instanceof MethodSymbol methodSymbol) {
return new JavacMethodBinding(methodSymbol, this, typeArguments);
return new JavacMethodBinding(ident.type.asMethodType(), methodSymbol, this);
}
if (javacElement instanceof JCFieldAccess fieldAccess && fieldAccess.sym instanceof MethodSymbol methodSymbol) {
return new JavacMethodBinding(methodSymbol, this, typeArguments);
return new JavacMethodBinding(fieldAccess.type.asMethodType(), methodSymbol, this);
}
return null;
}
Expand All @@ -227,7 +225,7 @@ IMethodBinding resolveMethod(MethodDeclaration method) {
resolve();
JCTree javacElement = this.converter.domToJavac.get(method);
if (javacElement instanceof JCMethodDecl methodDecl) {
return new JavacMethodBinding(methodDecl.sym, this, null);
return new JavacMethodBinding(methodDecl.type.asMethodType(), methodDecl.sym, this);
}
return null;
}
Expand All @@ -239,18 +237,17 @@ IBinding resolveName(Name name) {
if (tree == null) {
tree = this.converter.domToJavac.get(name.getParent());
}
final java.util.List<TypeSymbol> typeArguments = getTypeArguments(name);
if (tree instanceof JCIdent ident && ident.sym != null) {
return getBinding(ident.sym, typeArguments);
return getBinding(ident.sym, ident.type);
}
if (tree instanceof JCFieldAccess fieldAccess && fieldAccess.sym != null) {
return getBinding(fieldAccess.sym, typeArguments);
return getBinding(fieldAccess.sym, fieldAccess.type);
}
if (tree instanceof JCClassDecl classDecl && classDecl.sym != null) {
return getBinding(classDecl.sym, typeArguments);
return getBinding(classDecl.sym, classDecl.type);
}
if (tree instanceof JCVariableDecl variableDecl && variableDecl.sym != null) {
return getBinding(variableDecl.sym, typeArguments);
return getBinding(variableDecl.sym, variableDecl.type);
}
return null;
}
Expand All @@ -272,7 +269,7 @@ public IPackageBinding resolvePackage(PackageDeclaration decl) {
public ITypeBinding resolveExpressionType(Expression expr) {
resolve();
return this.converter.domToJavac.get(expr) instanceof JCExpression jcExpr ?
new JavacTypeBinding(jcExpr.type, this, null) :
new JavacTypeBinding(jcExpr.type, this) :
null;
}

Expand Down Expand Up @@ -356,7 +353,7 @@ public Object getValueFromAttribute(Attribute attribute) {
if (attribute instanceof Attribute.Constant constant) {
return constant.value;
} else if (attribute instanceof Attribute.Class clazz) {
return new JavacTypeBinding(clazz.classType.tsym, this, null);
return new JavacTypeBinding(clazz.classType, this);
} else if (attribute instanceof Attribute.Enum enumm) {
return new JavacVariableBinding(enumm.value, this);
} else if (attribute instanceof Attribute.Array array) {
Expand All @@ -365,7 +362,7 @@ public Object getValueFromAttribute(Attribute attribute) {
if (attribute instanceof Attribute.Constant constant) {
return constant.value;
} else if (attribute instanceof Attribute.Class clazz) {
return new JavacTypeBinding(clazz.classType.tsym, this, null);
return new JavacTypeBinding(clazz.classType, this);
} else if (attribute instanceof Attribute.Enum enumerable) {
return new JavacVariableBinding(enumerable.value, this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public IMemberValuePairBinding[] getAllMemberValuePairs() {

@Override
public ITypeBinding getAnnotationType() {
return new JavacTypeBinding(this.annotation.type, this.resolver, null);
return new JavacTypeBinding(this.annotation.type, this.resolver);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class JavacMemberValuePairBinding implements IMemberValuePairBinding {
private final JavacBindingResolver resolver;

public JavacMemberValuePairBinding(MethodSymbol key, Attribute value, JavacBindingResolver resolver) {
this.method = new JavacMethodBinding(key, resolver, null);
this.method = new JavacMethodBinding(key.type.asMethodType(), key, resolver);
this.value = value;
this.resolver = resolver;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,21 @@
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Type.JCNoType;
import com.sun.tools.javac.code.Type.MethodType;

public class JavacMethodBinding implements IMethodBinding {

private static final ITypeBinding[] NO_TYPE_ARGUMENTS = new ITypeBinding[0];

public final MethodSymbol methodSymbol;
private final MethodType methodType;
final JavacBindingResolver resolver;
private final List<TypeSymbol> typeArguments;

public JavacMethodBinding(MethodSymbol sym, JavacBindingResolver resolver, List<TypeSymbol> typeArguments) {
this.methodSymbol = sym;
public JavacMethodBinding(MethodType methodType, MethodSymbol methodSymbol, JavacBindingResolver resolver) {
this.methodType = methodType;
this.methodSymbol = methodSymbol;
this.resolver = resolver;
this.typeArguments = typeArguments;
}

@Override
Expand Down Expand Up @@ -109,7 +113,7 @@ public boolean isSynthetic() {

@Override
public IJavaElement getJavaElement() {
IJavaElement parent = this.resolver.getBinding(this.methodSymbol.owner, null).getJavaElement();
IJavaElement parent = this.resolver.getBinding(this.methodSymbol.owner, this.methodType).getJavaElement();
if (parent instanceof IType type) {
return type.getMethod(this.methodSymbol.getSimpleName().toString(),
this.methodSymbol.params().stream()
Expand All @@ -123,30 +127,47 @@ public IJavaElement getJavaElement() {
@Override
public String getKey() {
StringBuilder builder = new StringBuilder();
getKey(builder, this.methodSymbol);
getKey(builder, this.methodSymbol, this.resolver);
return builder.toString();
}

static void getKey(StringBuilder builder, MethodSymbol methodSymbol) {
static void getKey(StringBuilder builder, MethodSymbol methodSymbol, JavacBindingResolver resolver) {
Symbol ownerSymbol = methodSymbol.owner;
while (ownerSymbol != null && !(ownerSymbol instanceof TypeSymbol)) {
ownerSymbol = ownerSymbol.owner;
}
if (ownerSymbol instanceof TypeSymbol ownerTypeSymbol) {
builder.append(ownerTypeSymbol.name);
JavacTypeBinding.getKey(builder, resolver.getTypes().erasure(ownerTypeSymbol.type), false);
} else {
throw new IllegalArgumentException("Method has no owning class");
}
builder.append('.');
// TODO: what is a selector? why is it added?
for (var typeParam : methodSymbol.getTypeParameters()) {
builder.append(typeParam.getQualifiedName());
if (!methodSymbol.isConstructor()) {
builder.append(methodSymbol.getSimpleName());
}
if (!methodSymbol.getTypeParameters().isEmpty()) {
builder.append('<');
for (var typeParam : methodSymbol.getTypeParameters()) {
JavacTypeVariableBinding typeVarBinding = new JavacTypeVariableBinding(typeParam);
builder.append(typeVarBinding.getKey());
}
builder.append('>');
}
builder.append('(');
for (var param : methodSymbol.getParameters()) {
builder.append(param.getQualifiedName());
JavacTypeBinding.getKey(builder, param.type, false);
}
for (var thrownException : methodSymbol.getThrownTypes()) {
builder.append(thrownException.tsym.getQualifiedName());
builder.append(')');
if (!(methodSymbol.getReturnType() instanceof JCNoType)) {
JavacTypeBinding.getKey(builder, methodSymbol.getReturnType(), false);
}
if (
methodSymbol.getThrownTypes().stream().anyMatch(a -> !a.getParameterTypes().isEmpty())
) {
builder.append('^');
for (var thrownException : methodSymbol.getThrownTypes()) {
builder.append(thrownException.tsym.getQualifiedName());
}
}
}

Expand Down Expand Up @@ -188,7 +209,7 @@ public ITypeBinding getDeclaringClass() {
Symbol parentSymbol = this.methodSymbol.owner;
do {
if (parentSymbol instanceof ClassSymbol clazz) {
return new JavacTypeBinding(clazz, this.resolver, null);
return new JavacTypeBinding(clazz.type, this.resolver);
}
parentSymbol = parentSymbol.owner;
} while (parentSymbol != null);
Expand All @@ -201,7 +222,7 @@ public IBinding getDeclaringMember() {
return null;
}
if (this.methodSymbol.owner instanceof MethodSymbol methodSymbol) {
return new JavacMethodBinding(methodSymbol, resolver, null);
return new JavacMethodBinding(methodSymbol.type.asMethodType(), methodSymbol, resolver);
} else if (this.methodSymbol.owner instanceof VarSymbol variableSymbol) {
return new JavacVariableBinding(variableSymbol, resolver);
}
Expand All @@ -225,18 +246,18 @@ public IAnnotationBinding[] getParameterAnnotations(int paramIndex) {
public ITypeBinding[] getParameterTypes() {
return this.methodSymbol.params().stream()
.map(param -> param.type)
.map(type -> new JavacTypeBinding(type, this.resolver, /* TODO */ null))
.map(type -> new JavacTypeBinding(type, this.resolver))
.toArray(ITypeBinding[]::new);
}

@Override
public ITypeBinding getDeclaredReceiverType() {
return new JavacTypeBinding(this.methodSymbol.getReceiverType(), this.resolver, /* TODO */ null);
return new JavacTypeBinding(this.methodSymbol.getReceiverType(), this.resolver);
}

@Override
public ITypeBinding getReturnType() {
return new JavacTypeBinding(this.methodSymbol.getReturnType(), this.resolver, /* TODO */ null);
return new JavacTypeBinding(this.methodSymbol.getReturnType(), this.resolver);
}

@SuppressWarnings("unchecked")
Expand All @@ -254,7 +275,7 @@ public ITypeBinding[] getExceptionTypes() {
@Override
public ITypeBinding[] getTypeParameters() {
return this.methodSymbol.getTypeParameters().stream()
.map(symbol -> new JavacTypeBinding(symbol, this.resolver, null))
.map(symbol -> new JavacTypeBinding(symbol.type, this.resolver))
.toArray(ITypeBinding[]::new);
}

Expand All @@ -265,18 +286,21 @@ public boolean isAnnotationMember() {

@Override
public boolean isGenericMethod() {
return this.typeArguments == null && !this.methodSymbol.getTypeParameters().isEmpty();
return this.methodType.getTypeArguments().isEmpty() && !this.methodSymbol.getTypeParameters().isEmpty();
}

@Override
public boolean isParameterizedMethod() {
return this.typeArguments != null;
return !this.methodType.getTypeArguments().isEmpty();
}

@Override
public ITypeBinding[] getTypeArguments() {
return this.typeArguments.stream()
.map(symbol -> new JavacTypeBinding(symbol, this.resolver, null))
if (this.methodType.getTypeArguments().isEmpty()) {
return NO_TYPE_ARGUMENTS;
}
return this.methodType.getTypeArguments().stream()
.map(type -> new JavacTypeBinding(type, this.resolver))
.toArray(ITypeBinding[]::new);
}

Expand Down
Loading

0 comments on commit d34d8af

Please sign in to comment.