Skip to content

Commit

Permalink
[javac] Retrieve the correct paramterization for enclosing types of m…
Browse files Browse the repository at this point in the history
…ethod descriptors by getting it from the qualifier.

Example:
Extra casts were inserted in the j2kt transpilation for bridgejsmethod (readables/java/bridgejsmethod) that are not avoided.
PiperOrigin-RevId: 718650259
  • Loading branch information
Googler authored and copybara-github committed Jan 23, 2025
1 parent 2a918cf commit 992d798
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.google.j2cl.common.visitor.Visitable;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;
import javax.annotation.Nullable;

/** An array type. */
Expand Down Expand Up @@ -233,6 +234,18 @@ public ArrayTypeDescriptor specializeTypeVariables(
return specializeTypeVariables(replacementTypeArgumentByTypeVariable, ImmutableSet.of());
}

@Override
@Nullable
public DeclaredTypeDescriptor findSupertype(TypeDeclaration supertypeDeclaration) {
return Stream.of(
TypeDescriptors.get().javaLangObject,
TypeDescriptors.get().javaLangCloneable,
TypeDescriptors.get().javaIoSerializable)
.filter(td -> td.getTypeDeclaration().equals(supertypeDeclaration))
.findFirst()
.orElse(null);
}

@Override
boolean isDenotable(ImmutableSet<TypeVariable> seen) {
return getComponentTypeDescriptor().isDenotable(seen);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1293,6 +1293,15 @@ public DeclaredTypeDescriptor withTypeArguments(Iterable<TypeDescriptor> typeArg
return toBuilder().setTypeArgumentDescriptors(typeArguments).build();
}

@Override
@Nullable
public DeclaredTypeDescriptor findSupertype(TypeDeclaration supertypeDeclaration) {
return getAllSuperTypesIncludingSelf().stream()
.filter(supertype -> supertype.getTypeDeclaration().equals(supertypeDeclaration))
.findFirst()
.orElse(null);
}

@Override
public String getReadableDescription() {
return getTypeDeclaration().getReadableDescription()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.j2cl.common.ThreadLocalInterner;
Expand Down Expand Up @@ -208,6 +209,16 @@ public IntersectionTypeDescriptor specializeTypeVariables(
return specializeTypeVariables(replacementTypeArgumentByTypeVariable, ImmutableSet.of());
}

@Override
@Nullable
public DeclaredTypeDescriptor findSupertype(TypeDeclaration supertypeDeclaration) {
return getIntersectionTypeDescriptors().stream()
.map(td -> td.findSupertype(supertypeDeclaration))
.filter(Predicates.notNull())
.findFirst()
.orElse(null);
}

@Override
boolean isDenotable(ImmutableSet<TypeVariable> seen) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,12 @@ public PrimitiveTypeDescriptor specializeTypeVariables(
return specializeTypeVariables(replacementTypeArgumentByTypeVariable, ImmutableSet.of());
}

@Override
@Nullable
public DeclaredTypeDescriptor findSupertype(TypeDeclaration supertypeDeclaration) {
throw new UnsupportedOperationException();
}

/** A unique string for a give type. Used for interning. */
@Override
public String getUniqueId() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,13 @@ abstract TypeDescriptor specializeTypeVariables(
public abstract TypeDescriptor specializeTypeVariables(
Function<TypeVariable, ? extends TypeDescriptor> replacementTypeArgumentByTypeVariable);

/**
* Finds the supertype of this type (or this type itself) that has the same base type as given.
* The returned type has the parameterization of the current type.
*/
@Nullable
public abstract DeclaredTypeDescriptor findSupertype(TypeDeclaration supertypeDeclaration);

/**
* Returns true if the two types have the same raw type.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,12 @@ public TypeDescriptor specializeTypeVariables(
return specializeTypeVariables(replacementTypeArgumentByTypeVariable, ImmutableSet.of());
}

@Override
@Nullable
public DeclaredTypeDescriptor findSupertype(TypeDeclaration supertypeDeclaration) {
return getUpperBoundTypeDescriptor().findSupertype(supertypeDeclaration);
}

@Override
public String getReadableDescription() {
return getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,17 @@ public UnionTypeDescriptor specializeTypeVariables(
return specializeTypeVariables(replacementTypeArgumentByTypeVariable, ImmutableSet.of());
}

@Override
@Nullable
public DeclaredTypeDescriptor findSupertype(TypeDeclaration supertypeDeclaration) {
return getUnionTypeDescriptors().stream()
.map(td -> td.findSupertype(supertypeDeclaration))
// Perform a reduction where if any value is null, the result is null.
// For union types, all types must have the given supertype in order to be considered.
.reduce((a, b) -> (a == null || b == null) ? null : a)
.orElse(null);
}

@Override
boolean isDenotable(ImmutableSet<TypeVariable> seen) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.google.j2cl.transpiler.frontend.javac;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.stream.Collectors.toCollection;
Expand Down Expand Up @@ -893,17 +894,24 @@ private Expression convertMemberReference(JCMemberReference memberReference) {
.build();
}

Expression qualifier = convertExpressionOrNull(memberReference.getQualifierExpression());
if (qualifier instanceof JavaScriptConstructorReference) {
// The qualifier was just the class name, remove it.
qualifier = null;
}

DeclaredTypeDescriptor enclosingTypeDescriptor =
getParameterizedEnclosingType(
environment.createDeclaredTypeDescriptor(methodSymbol.getEnclosingElement().asType()),
qualifier);

List<TypeDescriptor> typeArguments = convertTypeArguments(memberReference.getTypeArguments());
MethodDescriptor targetMethodDescriptor =
environment.createMethodDescriptor(
enclosingTypeDescriptor,
/* methodType= */ memberReference.referentType.asMethodType(),
/* declarationMethodElement= */ methodSymbol,
typeArguments);
Expression qualifier = convertExpressionOrNull(memberReference.getQualifierExpression());
if (qualifier instanceof JavaScriptConstructorReference) {
// The qualifier was just the class name, remove it.
qualifier = null;
}

return MethodReference.newBuilder()
.setTypeDescriptor(expressionTypeDescriptor)
Expand Down Expand Up @@ -1052,9 +1060,18 @@ private Expression convertMethodInvocation(JCMethodInvocation methodInvocation)
qualifier = null;
}

// The type arguments for the method itself. For example `String` in `C.<String>m()`.
var typeArguments = convertTypeArguments(methodInvocation.getTypeArguments());

DeclaredTypeDescriptor enclosingTypeDescriptor =
environment.createDeclaredTypeDescriptor(methodSymbol.getEnclosingElement().asType());
if (!methodSymbol.isConstructor()) {
enclosingTypeDescriptor = getParameterizedEnclosingType(enclosingTypeDescriptor, qualifier);
}

MethodDescriptor methodDescriptor =
environment.createMethodDescriptor(
/* enclosingTypeDescriptor= */ enclosingTypeDescriptor,
/* methodType= */ methodInvocation.getMethodSelect().type.asMethodType(),
/* declarationMethodElement= */ methodSymbol,
typeArguments);
Expand Down Expand Up @@ -1142,6 +1159,23 @@ private static JCExpression getExplicitQualifier(JCMethodInvocation methodInvoca
return getQualifier(methodInvocation.getMethodSelect());
}

private DeclaredTypeDescriptor getParameterizedEnclosingType(
DeclaredTypeDescriptor enclosingTypeDescriptor, Expression qualifier) {
if (qualifier == null) {
return enclosingTypeDescriptor;
}

if (qualifier.getTypeDescriptor().isRaw()) {
return enclosingTypeDescriptor.toRawTypeDescriptor();
}

// In order to get the correct parameterization, find the parameterized type from the qualifier,
// if available. The methodSymbol's enclosing element will not have the necessary type
// information from javac.
return checkNotNull(
qualifier.getTypeDescriptor().findSupertype(enclosingTypeDescriptor.getTypeDeclaration()));
}

private Expression convertIdent(JCIdent identifier) {
if (isThisExpression(identifier)) {
return new ThisReference(getCurrentType().getTypeDescriptor());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -616,24 +616,6 @@ FieldDescriptor createFieldDescriptor(VariableElement variableElement, TypeMirro
.build();
}

/**
* Creates a MethodDescriptor from javac internal representation.
*
* @param methodType an ExecutableType containing the (inferred) specialization of the method in a
* usage location.
* @param declarationMethodElement the method declaration.
*/
MethodDescriptor createMethodDescriptor(
ExecutableType methodType,
ExecutableElement declarationMethodElement,
List<TypeDescriptor> typeArguments) {

DeclaredTypeDescriptor enclosingTypeDescriptor =
createDeclaredTypeDescriptor(declarationMethodElement.getEnclosingElement().asType());
return createMethodDescriptor(
enclosingTypeDescriptor, methodType, declarationMethodElement, typeArguments);
}

/** Create a MethodDescriptor directly based on the given JavaC ExecutableElement. */
MethodDescriptor createMethodDescriptor(
DeclaredTypeDescriptor enclosingTypeDescriptor,
Expand Down

0 comments on commit 992d798

Please sign in to comment.