Skip to content

Commit

Permalink
[J2KT] Add debug logging to InsertQualifierProjectionCasts, and `De…
Browse files Browse the repository at this point in the history
…scriber.getDescription()` methods for `TypeDeclaration` and `MethodDescriptor` which will be used in follow-up CLs.

PiperOrigin-RevId: 730595017
  • Loading branch information
Googler authored and copybara-github committed Feb 24, 2025
1 parent 65ae4a1 commit 5a4687e
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,19 @@
import static java.util.stream.Collectors.joining;

import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.FormatMethod;
import com.google.j2cl.common.SourcePosition;
import com.google.j2cl.transpiler.ast.AbstractRewriter;
import com.google.j2cl.transpiler.ast.ArrayTypeDescriptor;
import com.google.j2cl.transpiler.ast.DeclaredTypeDescriptor;
import com.google.j2cl.transpiler.ast.HasSourcePosition;
import com.google.j2cl.transpiler.ast.IntersectionTypeDescriptor;
import com.google.j2cl.transpiler.ast.MethodDescriptor;
import com.google.j2cl.transpiler.ast.MethodDescriptor.ParameterDescriptor;
import com.google.j2cl.transpiler.ast.NullabilityAnnotation;
import com.google.j2cl.transpiler.ast.PrimitiveTypeDescriptor;
import com.google.j2cl.transpiler.ast.Type;
import com.google.j2cl.transpiler.ast.TypeDeclaration;
import com.google.j2cl.transpiler.ast.TypeDescriptor;
import com.google.j2cl.transpiler.ast.TypeVariable;
import com.google.j2cl.transpiler.ast.UnionTypeDescriptor;
Expand All @@ -38,19 +46,68 @@
* </ul>
*/
public abstract class AbstractJ2ktNormalizationPass extends NormalizationPass {
private final Describer describer = new Describer();

// Prevent overriding and force using {@code applyTo(CompilationUnit)}.
@Override
public final void applyTo(Type type) {}

final Describer getDescriber() {
return describer;
}

@FormatMethod
final void debug(SourcePosition sourcePosition, String detailMessage, Object... args) {
getProblems().debug(sourcePosition, detailMessage, args);
}

@FormatMethod
final void debug(String detailMessage, Object... args) {
debug(SourcePosition.NONE, detailMessage, args);
}

/** Returns the closest meaningful source position from an enclosing node. */
final SourcePosition getSourcePosition(AbstractRewriter rewriter) {
HasSourcePosition hasSourcePosition =
(HasSourcePosition) rewriter.getParent(HasSourcePosition.class::isInstance);
return hasSourcePosition != null ? hasSourcePosition.getSourcePosition() : SourcePosition.NONE;
}

final String getDescription(TypeDescriptor typeDescriptor) {
return describer.getDescription(typeDescriptor, ImmutableList.of());
}

final String getDescription(TypeDeclaration typeDeclaration) {
return describer.getDescription(typeDeclaration);
}

final String getDescription(MethodDescriptor methodDescriptor) {
return describer.getDescription(methodDescriptor);
}

final String getTypeParameterDescription(TypeVariable typeVariable) {
return describer.getTypeParameterDescription(typeVariable);
}

/**
* Produces readable description string for AST nodes, containing information about resolved
* nullability and captures with unique IDs. Used in Kotlin passes for debugging / development.
*/
// TODO(b/382500942): Remove when no longer needed for debugging / development.
static final class Describer {
private static final class Describer {
private final List<TypeVariable> seenCaptures = new ArrayList<>();

String getDescription(TypeDescriptor typeDescriptor) {
private Describer() {}

private String getDescription(TypeDescriptor typeDescriptor) {
return getDescription(typeDescriptor, ImmutableList.of());
}

private String getDescription(TypeDeclaration typeDeclaration) {
return typeDeclaration.getReadableDescription()
+ getTypeParametersDescription(typeDeclaration.getTypeParameterDescriptors());
}

@Nullable
private static String getDescription(NullabilityAnnotation nullabilityAnnotation) {
switch (nullabilityAnnotation) {
Expand All @@ -64,6 +121,28 @@ private static String getDescription(NullabilityAnnotation nullabilityAnnotation
throw new AssertionError();
}

private String getDescription(MethodDescriptor methodDescriptor) {
return String.format(
"%s%s (%s).%s%s%s",
appendSpaceIfNotEmpty(
getTypeParametersDescription(methodDescriptor.getTypeParameterTypeDescriptors())),
getDescription(methodDescriptor.getReturnTypeDescriptor()),
getDescription(methodDescriptor.getEnclosingTypeDescriptor()),
getTypeArgumentsDescription(methodDescriptor.getTypeArgumentTypeDescriptors()),
methodDescriptor.getName(),
getParametersDescription(methodDescriptor.getParameterDescriptors()));
}

private String getDescription(ParameterDescriptor parameterDescriptor) {
TypeDescriptor typeDescriptor = parameterDescriptor.getTypeDescriptor();
if (parameterDescriptor.isVarargs()) {
ArrayTypeDescriptor arrayTypeDescriptor = (ArrayTypeDescriptor) typeDescriptor;
return getDescription(arrayTypeDescriptor.getComponentTypeDescriptor()) + "...";
} else {
return getDescription(parameterDescriptor.getTypeDescriptor());
}
}

private String getDescription(
TypeDescriptor typeDescriptor, ImmutableList<TypeVariable> enclosingWildcardOrCaptures) {
if (typeDescriptor instanceof PrimitiveTypeDescriptor) {
Expand Down Expand Up @@ -100,17 +179,37 @@ private String getDescription(
}
}

private String getParametersDescription(
ImmutableList<ParameterDescriptor> parameterDescriptors) {
return parameterDescriptors.stream()
.map(this::getDescription)
.collect(joining(", ", "(", ")"));
}

private String getTypeParameterDescription(TypeVariable typeVariable) {
return typeVariable.getName()
+ " extends "
+ getDescription(typeVariable.getUpperBoundTypeDescriptor());
}

private String getTypeParametersDescription(ImmutableList<TypeVariable> typeParameters) {
return inAngleBracketsIfNotEmpty(
typeParameters.stream().map(this::getTypeParameterDescription).collect(joining(", ")));
}

private String getTypeArgumentsDescription(ImmutableList<TypeDescriptor> typeArguments) {
return inAngleBracketsIfNotEmpty(
typeArguments.stream().map(this::getDescription).collect(joining(", ")));
}

private String getTypeArgumentsDescription(
DeclaredTypeDescriptor declaredTypeDescriptor,
ImmutableList<TypeVariable> enclosingWildcardOrCaptures) {
ImmutableList<TypeDescriptor> arguments = declaredTypeDescriptor.getTypeArgumentDescriptors();
if (arguments.isEmpty()) {
return "";
} else {
return arguments.stream()
.map(it -> getDescription(it, enclosingWildcardOrCaptures))
.collect(joining(", ", "<", ">"));
}
return inAngleBracketsIfNotEmpty(
arguments.stream()
.map(it -> getDescription(it, enclosingWildcardOrCaptures))
.collect(joining(", ")));
}

private String getDescriptionWithoutNullabilityAnnotation(
Expand Down Expand Up @@ -178,4 +277,12 @@ private static String getDescriptionInfix(NullabilityAnnotation nullabilityAnnot
return description == null ? "" : " " + description + " ";
}
}

private static String appendSpaceIfNotEmpty(String string) {
return string.isEmpty() ? string : string + " ";
}

private static String inAngleBracketsIfNotEmpty(String string) {
return string.isEmpty() ? string : "<" + string + ">";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,13 @@ public Expression rewriteTypeConversionContext(
return expression;
}

Describer describer = new Describer();
getProblems()
.debug(
getSourcePosition(),
"Inserted nullability mismatch cast to '%s' because of assignment from '%s'"
+ " to '%s'",
describer.getDescription(castTypeDescriptor),
describer.getDescription(expression.getTypeDescriptor()),
describer.getDescription(inferredTypeDescriptor));
debug(
getSourcePosition(),
"Inserted nullability mismatch cast to '%s' because of assignment from '%s'"
+ " to '%s'",
getDescription(castTypeDescriptor),
getDescription(expression.getTypeDescriptor()),
getDescription(inferredTypeDescriptor));

return CastExpression.newBuilder()
.setExpression(expression)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
* }
* }</pre>
*/
public final class InsertQualifierProjectionCasts extends NormalizationPass {
public final class InsertQualifierProjectionCasts extends AbstractJ2ktNormalizationPass {
@Override
public void applyTo(CompilationUnit compilationUnit) {
// TODO(b/362477320): Consider switching to ConversionContextVisitor, once
Expand All @@ -99,6 +99,12 @@ private Expression projectExpression(Expression expression) {
return expression;
}

debug(
getSourcePosition(this),
"Inserting qualifier projection cast from %s to %s",
getDescription(typeDescriptor),
getDescription(projectedTypeDescriptor));

return CastExpression.newBuilder()
.setExpression(expression)
.setCastTypeDescriptor(projectedTypeDescriptor)
Expand Down

0 comments on commit 5a4687e

Please sign in to comment.