From 32fe079441cfa7a06a2b942d69ec686d6e48d21b Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Fri, 2 Aug 2024 17:37:42 -0700 Subject: [PATCH] Plumb `VisitorState` through to `Signatures` PiperOrigin-RevId: 658956389 --- .../google/errorprone/util/Signatures.java | 45 ++++++++++++------- .../bugpatterns/AmbiguousMethodReference.java | 10 ++--- .../bugpatterns/FunctionalInterfaceClash.java | 6 +-- .../bugpatterns/apidiff/ApiDiffChecker.java | 8 ++-- 4 files changed, 41 insertions(+), 28 deletions(-) diff --git a/check_api/src/main/java/com/google/errorprone/util/Signatures.java b/check_api/src/main/java/com/google/errorprone/util/Signatures.java index eae84060f2c4..ab8ad1a68b58 100644 --- a/check_api/src/main/java/com/google/errorprone/util/Signatures.java +++ b/check_api/src/main/java/com/google/errorprone/util/Signatures.java @@ -16,42 +16,57 @@ package com.google.errorprone.util; -import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.stream.Collectors.joining; +import com.google.errorprone.VisitorState; import com.sun.tools.javac.code.BoundKind; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Types; import com.sun.tools.javac.code.Types.DefaultTypeVisitor; -import com.sun.tools.javac.code.Types.SignatureGenerator; import com.sun.tools.javac.util.Name; -import java.util.Arrays; +import com.sun.tools.javac.util.Names; /** Signature generation. */ public final class Signatures { /** Returns the binary names of the class. */ - public static String classDescriptor(Type type, Types types) { - SigGen sig = new SigGen(types); + public static String classDescriptor(Type type, VisitorState state) { + return new Signatures(state).classDescriptor(type); + } + + private String classDescriptor(Type type) { + SigGen sig = new SigGen(); sig.assembleClassSig(types.erasure(type)); return sig.toString(); } /** Returns a JVMS 4.3.3 method descriptor. */ - public static String descriptor(Type type, Types types) { - SigGen sig = new SigGen(types); + public static String descriptor(Type type, VisitorState state) { + return new Signatures(state).descriptor(type); + } + + private String descriptor(Type type) { + SigGen sig = new SigGen(); sig.assembleSig(types.erasure(type)); return sig.toString(); } - private static class SigGen extends SignatureGenerator { + final Types types; + final Names names; + + private Signatures(VisitorState state) { + this.types = state.getTypes(); + this.names = state.getNames(); + } + + private class SigGen extends Types.SignatureGenerator { private final com.sun.tools.javac.util.ByteBuffer buffer = new com.sun.tools.javac.util.ByteBuffer(); - protected SigGen(Types types) { + protected SigGen() { super(types); } @@ -70,12 +85,14 @@ protected void append(Name name) { buffer.appendName(name); } + @SuppressWarnings("CatchingUnchecked") // handles InvalidUtfException on JDK 21+ @Override public String toString() { - // We could use buffer.toName(Names), but we want a string anyways and this - // avoids plumbing a Context or instances of Names through. - // Names always uses UTF-8 internally. - return new String(Arrays.copyOf(buffer.elems, buffer.length), UTF_8); + try { + return buffer.toName(names).toString(); + } catch (Exception e) { + throw new AssertionError(e); + } } } @@ -154,6 +171,4 @@ public String visitType(Type t, Void s) { return t.toString(); } }; - - private Signatures() {} } diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/AmbiguousMethodReference.java b/core/src/main/java/com/google/errorprone/bugpatterns/AmbiguousMethodReference.java index 11b26d7fa549..20b6fa7ce32c 100644 --- a/core/src/main/java/com/google/errorprone/bugpatterns/AmbiguousMethodReference.java +++ b/core/src/main/java/com/google/errorprone/bugpatterns/AmbiguousMethodReference.java @@ -59,7 +59,7 @@ public Description matchClass(ClassTree tree, VisitorState state) { .map(MethodSymbol.class::cast) .filter(m -> m.isConstructor() || m.owner.equals(origin)) .collect( - groupingBy(m -> methodReferenceDescriptor(types, m), toCollection(ArrayList::new))); + groupingBy(m -> methodReferenceDescriptor(state, m), toCollection(ArrayList::new))); // look for groups of ambiguous method references for (Tree member : tree.getMembers()) { @@ -70,7 +70,7 @@ public Description matchClass(ClassTree tree, VisitorState state) { if (isSuppressed(msym, state)) { continue; } - List clash = methods.remove(methodReferenceDescriptor(types, msym)); + List clash = methods.remove(methodReferenceDescriptor(state, msym)); if (clash == null) { continue; } @@ -104,13 +104,13 @@ public Description matchClass(ClassTree tree, VisitorState state) { } /** Returns a string descriptor of a method's reference type. */ - private static String methodReferenceDescriptor(Types types, MethodSymbol sym) { + private static String methodReferenceDescriptor(VisitorState state, MethodSymbol sym) { StringBuilder sb = new StringBuilder(); sb.append(sym.getSimpleName()).append('('); if (!sym.isStatic()) { - sb.append(Signatures.descriptor(sym.owner.type, types)); + sb.append(Signatures.descriptor(sym.owner.type, state)); } - sym.params().stream().map(p -> Signatures.descriptor(p.type, types)).forEachOrdered(sb::append); + sym.params().stream().map(p -> Signatures.descriptor(p.type, state)).forEachOrdered(sb::append); sb.append(")"); return sb.toString(); } diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/FunctionalInterfaceClash.java b/core/src/main/java/com/google/errorprone/bugpatterns/FunctionalInterfaceClash.java index fb2b227c4b5c..7141f6246907 100644 --- a/core/src/main/java/com/google/errorprone/bugpatterns/FunctionalInterfaceClash.java +++ b/core/src/main/java/com/google/errorprone/bugpatterns/FunctionalInterfaceClash.java @@ -171,7 +171,7 @@ private static String functionalInterfaceSignature(VisitorState state, MethodSym private static String functionalInterfaceSignature(VisitorState state, Type type) { Types types = state.getTypes(); if (!maybeFunctionalInterface(type, types, state)) { - return Signatures.descriptor(type, types); + return Signatures.descriptor(type, state); } Type descriptorType = types.findDescriptorType(type); List fiparams = descriptorType.getParameterTypes(); @@ -180,10 +180,10 @@ private static String functionalInterfaceSignature(VisitorState state, Type type // types in general. The except is nullary functional interfaces, since the lambda parameters // will never be implicitly typed. String result = - fiparams.isEmpty() ? Signatures.descriptor(descriptorType.getReturnType(), types) : "_"; + fiparams.isEmpty() ? Signatures.descriptor(descriptorType.getReturnType(), state) : "_"; return String.format( "(%s)->%s", - fiparams.stream().map(t -> Signatures.descriptor(t, types)).collect(joining(",")), result); + fiparams.stream().map(t -> Signatures.descriptor(t, state)).collect(joining(",")), result); } private static boolean maybeFunctionalInterface(Type type, Types types, VisitorState state) { diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/apidiff/ApiDiffChecker.java b/core/src/main/java/com/google/errorprone/bugpatterns/apidiff/ApiDiffChecker.java index f59064a7eb3c..2ccd70757b9b 100644 --- a/core/src/main/java/com/google/errorprone/bugpatterns/apidiff/ApiDiffChecker.java +++ b/core/src/main/java/com/google/errorprone/bugpatterns/apidiff/ApiDiffChecker.java @@ -35,7 +35,6 @@ import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Type; -import com.sun.tools.javac.code.Types; import java.lang.annotation.Annotation; import java.util.Optional; import org.jspecify.annotations.Nullable; @@ -80,9 +79,8 @@ protected Description check(ExpressionTree tree, VisitorState state) { // e.g. package symbols return Description.NO_MATCH; } - Types types = state.getTypes(); // check for information associated with the class - if (apiDiff.isClassUnsupported(Signatures.classDescriptor(receiver.type, types)) + if (apiDiff.isClassUnsupported(Signatures.classDescriptor(receiver.type, state)) || classOrEnclosingClassIsForbiddenByAnnotation(receiver, state)) { return buildDescription(tree) .setMessage(String.format("%s is not available", receiver)) @@ -94,9 +92,9 @@ protected Description check(ExpressionTree tree, VisitorState state) { } ClassMemberKey memberKey = ClassMemberKey.create( - sym.getSimpleName().toString(), Signatures.descriptor(sym.type, types)); + sym.getSimpleName().toString(), Signatures.descriptor(sym.type, state)); ClassSymbol owner = sym.owner.enclClass(); - if (apiDiff.isMemberUnsupported(Signatures.classDescriptor(owner.type, types), memberKey) + if (apiDiff.isMemberUnsupported(Signatures.classDescriptor(owner.type, state), memberKey) || hasAnnotationForbiddingUse(sym, state)) { return buildDescription(tree) .setMessage(String.format("%s#%s is not available in %s", owner, sym, receiver))