Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/workaround bindings for generics vs parameterized #694

Merged
merged 1 commit into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ public JavacTypeBinding getTypeBinding(JCTree tree, com.sun.tools.javac.code.Typ
return getTypeBinding(type, tree instanceof JCClassDecl);
}
public JavacTypeBinding getTypeBinding(com.sun.tools.javac.code.Type type) {
return getTypeBinding(type, false);
return getTypeBinding(type.baseType() /* remove metadata for constant values */, false);
}
public JavacTypeBinding getTypeBinding(com.sun.tools.javac.code.Type type, boolean isDeclaration) {
if (type instanceof com.sun.tools.javac.code.Type.TypeVar typeVar) {
Expand Down Expand Up @@ -513,7 +513,7 @@ ITypeBinding resolveType(EnumDeclaration enumDecl) {
resolve();
JCTree javacNode = this.converter.domToJavac.get(enumDecl);
if (javacNode instanceof JCClassDecl jcClassDecl && jcClassDecl.type != null) {
return this.bindings.getTypeBinding(jcClassDecl.type);
return this.bindings.getTypeBinding(jcClassDecl.type, true);
}
return null;
}
Expand All @@ -523,7 +523,7 @@ ITypeBinding resolveType(AnonymousClassDeclaration anonymousClassDecl) {
resolve();
JCTree javacNode = this.converter.domToJavac.get(anonymousClassDecl);
if (javacNode instanceof JCClassDecl jcClassDecl && jcClassDecl.type != null) {
return this.bindings.getTypeBinding(jcClassDecl.type);
return this.bindings.getTypeBinding(jcClassDecl.type, true);
}
return null;
}
Expand Down Expand Up @@ -753,11 +753,13 @@ private IBinding resolveNameImpl(Name name) {
}

IBinding resolveNameToJavac(Name name, JCTree tree) {
boolean isTypeDeclaration = (name.getParent() instanceof AbstractTypeDeclaration typeDeclaration && typeDeclaration.getName() == name)
|| (name.getParent() instanceof SimpleType type && type.getName() == name);
if( name.getParent() instanceof AnnotatableType st && st.getParent() instanceof ParameterizedType pt) {
if( st == pt.getType()) {
tree = this.converter.domToJavac.get(pt);
if (!tree.type.isErroneous()) {
IBinding b = this.bindings.getTypeBinding(tree.type);
IBinding b = this.bindings.getTypeBinding(tree.type, isTypeDeclaration);
if( b != null ) {
return b;
}
Expand All @@ -770,6 +772,9 @@ IBinding resolveNameToJavac(Name name, JCTree tree) {
&& errorType.getOriginalType() instanceof ErrorType) {
return null;
}
if (isTypeDeclaration) {
return this.bindings.getTypeBinding(ident.type != null ? ident.type : ident.sym.type, true);
}
return this.bindings.getBinding(ident.sym, ident.type != null ? ident.type : ident.sym.type);
}
if (tree instanceof JCFieldAccess fieldAccess && fieldAccess.sym != null) {
Expand Down Expand Up @@ -1114,7 +1119,7 @@ public ITypeBinding resolveWellKnownType(String typeName) {
if (type == null) {
return null;
}
return this.bindings.getTypeBinding(type);
return this.bindings.getTypeBinding(type, true);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ public abstract class JavacTypeBinding implements ITypeBinding {
public final TypeSymbol typeSymbol;
private final Types types;
private final Type type;
private boolean isDeclaration;
private final boolean isGeneric; // only relevent for parameterized types
private boolean recovered = false;

public JavacTypeBinding(final Type type, final TypeSymbol typeSymbol, boolean isDeclaration, JavacBindingResolver resolver) {
if (type instanceof PackageType) {
throw new IllegalArgumentException("Use JavacPackageBinding");
}
this.type = type;
this.isDeclaration = isDeclaration;
this.isGeneric = type.isParameterized() && isDeclaration;
this.resolver = resolver;
this.types = Types.instance(this.resolver.context);
// TODO: consider getting rid of typeSymbol in constructor and always derive it from type
Expand All @@ -112,11 +112,12 @@ public boolean equals(Object obj) {
return obj instanceof JavacTypeBinding other
&& Objects.equals(this.resolver, other.resolver)
&& Objects.equals(this.type, other.type)
&& Objects.equals(this.typeSymbol, other.typeSymbol);
&& Objects.equals(this.typeSymbol, other.typeSymbol)
&& Objects.equals(this.isGeneric, other.isGeneric);
}
@Override
public int hashCode() {
return Objects.hash(this.resolver, this.type, this.typeSymbol);
return Objects.hash(this.resolver, this.type, this.typeSymbol, this.isGeneric);
}

@Override
Expand Down Expand Up @@ -250,10 +251,27 @@ private static String cleanedUpName(Type type) {

@Override
public String getKey() {
if (isGenericType()) {
return removeTrailingSemicolon(getKey(false)) + '<'
+ Arrays.stream(getTypeParameters())
.map(ITypeBinding::getName)
.map(name -> 'T' + name + ';')
.collect(Collectors.joining())
+ ">;";
} else if (isParameterizedType()) {
return removeTrailingSemicolon(getKey(false)) + '<'
+ Arrays.stream(getTypeArguments()).map(ITypeBinding::getKey).collect(Collectors.joining())
+ ">;";
}
return getKey(this.type, this.typeSymbol.flatName());
}

public String getKey(Type t) {

private static String removeTrailingSemicolon(String key) {
return key.endsWith(";") ? key.substring(0, key.length() - 1) : key;
}

private String getKey(Type t) {
return getKey(t, this.typeSymbol.flatName());
}

Expand Down Expand Up @@ -497,7 +515,7 @@ public ITypeBinding getDeclaringClass() {
Symbol parentSymbol = this.typeSymbol.owner;
do {
if (parentSymbol instanceof final ClassSymbol clazz) {
return this.resolver.bindings.getTypeBinding(clazz.type);
return this.resolver.bindings.getTypeBinding(clazz.type, true);
}
parentSymbol = parentSymbol.owner;
} while (parentSymbol != null);
Expand Down Expand Up @@ -550,6 +568,14 @@ public ITypeBinding getElementType() {

@Override
public ITypeBinding getErasure() {
if (isParameterizedType()) {
// generic binding
return this.resolver.bindings.getTypeBinding(this.type, true);
}
if (isRawType() && this.typeSymbol.type.isParameterized()) {
// generic binding
return this.resolver.bindings.getTypeBinding(this.typeSymbol.type, true);
}
return this.resolver.bindings.getTypeBinding(this.types.erasureRecursive(this.type));
}

Expand Down Expand Up @@ -619,7 +645,7 @@ public String getName() {
return builder.toString();
}
StringBuilder builder = new StringBuilder(this.typeSymbol.getSimpleName().toString());
if( !this.isDeclaration) {
if(isParameterizedType()) {
ITypeBinding[] types = this.getUncheckedTypeArguments(this.type, this.typeSymbol);
if (types != null && types.length > 0) {
builder.append("<");
Expand All @@ -644,7 +670,7 @@ public IPackageBinding getPackage() {

@Override
public String getQualifiedName() {
return getQualifiedNameImpl(this.type, this.typeSymbol, this.typeSymbol.owner, !this.isDeclaration);
return getQualifiedNameImpl(this.type, this.typeSymbol, this.typeSymbol.owner, !this.isGeneric);
}
protected String getQualifiedNameImpl(Type type, TypeSymbol typeSymbol, Symbol owner, boolean includeParameters) {
if (owner instanceof MethodSymbol) {
Expand Down Expand Up @@ -691,7 +717,7 @@ protected String getQualifiedNameImpl(Type type, TypeSymbol typeSymbol, Symbol o
res.append(typeSymbol.toString());
}

if( includeParameters ) {
if (includeParameters) {
ITypeBinding[] typeArguments = getUncheckedTypeArguments(type, typeSymbol);
boolean isTypeDeclaration = typeSymbol != null && typeSymbol.type == type;
if (!isTypeDeclaration && typeArguments.length > 0) {
Expand Down Expand Up @@ -767,15 +793,12 @@ public IAnnotationBinding[] getTypeAnnotations() {

@Override
public ITypeBinding[] getTypeArguments() {
return getTypeArguments(this.type, this.typeSymbol);
}

private ITypeBinding[] getTypeArguments(Type t, TypeSymbol ts) {
if (t == ts.type || t.getTypeArguments().isEmpty() || isTargettingPreGenerics()) {
if (!isParameterizedType() || isTargettingPreGenerics()) {
return NO_TYPE_ARGUMENTS;
}
return getUncheckedTypeArguments(t, ts);
return getUncheckedTypeArguments(this.type, this.typeSymbol);
}

private ITypeBinding[] getUncheckedTypeArguments(Type t, TypeSymbol ts) {
return t.getTypeArguments()
.stream()
Expand Down Expand Up @@ -833,14 +856,17 @@ public ITypeBinding[] getTypeBounds() {

@Override
public ITypeBinding getTypeDeclaration() {
if (this.isParameterizedType() || this.isRawType()) {
return getErasure();
}
return this.typeSymbol.type == this.type
? this
: this.resolver.bindings.getTypeBinding(this.typeSymbol.type);
}

@Override
public ITypeBinding[] getTypeParameters() {
if( isRawType() || getTypeArguments() == NO_TYPE_ARGUMENTS || !(this.type instanceof ClassType)) {
if(!isGenericType() || isTargettingPreGenerics()) {
return new ITypeBinding[0];
}
return ((ClassType)this.type).getTypeArguments()
Expand Down Expand Up @@ -919,7 +945,7 @@ public boolean isFromSource() {

@Override
public boolean isGenericType() {
return this.type.isParameterized() && this.isDeclaration && this.type.getTypeArguments().stream().anyMatch(TypeVar.class::isInstance);
return this.type.isParameterized() && this.isGeneric;
}

@Override
Expand Down Expand Up @@ -962,7 +988,7 @@ public boolean isNullType() {

@Override
public boolean isParameterizedType() {
return !this.type.getTypeArguments().isEmpty();
return this.type.isParameterized() && !this.isGeneric;
}

@Override
Expand Down