Skip to content

Commit 851e0b0

Browse files
cushonError Prone Team
authored andcommitted
Remove obsolete uses of reflection from Error Prone
PiperOrigin-RevId: 822565953
1 parent 344e3dc commit 851e0b0

File tree

5 files changed

+23
-162
lines changed

5 files changed

+23
-162
lines changed

core/src/main/java/com/google/errorprone/bugpatterns/WildcardImport.java

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
import com.google.errorprone.util.ASTHelpers;
3232
import com.sun.source.tree.CaseTree;
3333
import com.sun.source.tree.CompilationUnitTree;
34-
import com.sun.source.tree.ExpressionTree;
34+
import com.sun.source.tree.ConstantCaseLabelTree;
3535
import com.sun.source.tree.IdentifierTree;
3636
import com.sun.source.tree.ImportTree;
3737
import com.sun.source.tree.MemberSelectTree;
@@ -43,15 +43,10 @@
4343
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
4444
import com.sun.tools.javac.tree.JCTree.JCIdent;
4545
import com.sun.tools.javac.tree.TreeScanner;
46-
import java.lang.invoke.MethodHandle;
47-
import java.lang.invoke.MethodHandles;
48-
import java.lang.invoke.MethodType;
4946
import java.util.LinkedHashSet;
5047
import java.util.List;
5148
import java.util.Map;
5249
import java.util.Set;
53-
import java.util.logging.Level;
54-
import java.util.logging.Logger;
5550
import java.util.stream.Collectors;
5651
import javax.lang.model.element.ElementKind;
5752

@@ -64,7 +59,6 @@
6459
tags = StandardTags.STYLE,
6560
link = "https://google.github.io/styleguide/javaguide.html?cl=head#s3.3.1-wildcard-imports")
6661
public class WildcardImport extends BugChecker implements CompilationUnitTreeMatcher {
67-
private static final Logger logger = Logger.getLogger(WildcardImport.class.getName());
6862

6963
/** Maximum number of members to import before switching to qualified names. */
7064
public static final int MAX_MEMBER_IMPORTS = 20;
@@ -213,24 +207,6 @@ static Fix createFix(
213207
return fix.build();
214208
}
215209

216-
private static final MethodHandle CONSTANT_CASE_LABEL_TREE_GET_EXPRESSION;
217-
218-
static {
219-
MethodHandle h;
220-
try {
221-
Class<?> constantCaseLabelTree = Class.forName("com.sun.source.tree.ConstantCaseLabelTree");
222-
h =
223-
MethodHandles.lookup()
224-
.findVirtual(
225-
constantCaseLabelTree,
226-
"getConstantExpression",
227-
MethodType.methodType(ExpressionTree.class));
228-
} catch (ReflectiveOperationException e) {
229-
h = null;
230-
}
231-
CONSTANT_CASE_LABEL_TREE_GET_EXPRESSION = h;
232-
}
233-
234210
/**
235211
* Add an import for {@code owner}, and qualify all on demand imported references to members of
236212
* owner by owner's simple name.
@@ -251,20 +227,9 @@ public Void visitIdentifier(IdentifierTree tree, Void unused) {
251227
// switch cases can refer to enum constants by simple name without importing them
252228
return null;
253229
}
254-
// In JDK 19, the tree representation of enum case-labels changes. We can't reference the
255-
// relevant API directly because then this code wouldn't compile on earlier JDK versions.
256-
// So instead we use method handles. The straightforward code would be:
257-
// if (parent.getKind() == Tree.Kind.CONSTANT_CASE_LABEL
258-
// && tree.equals(((ConstantCaseLabelTree) parent).getConstantExpression())) {...}
259-
if (parent.getKind().name().equals("CONSTANT_CASE_LABEL")) {
260-
try {
261-
if (tree.equals(CONSTANT_CASE_LABEL_TREE_GET_EXPRESSION.invoke(parent))) {
262-
return null;
263-
}
264-
} catch (Throwable e) {
265-
// MethodHandle.invoke obliges us to catch Throwable here.
266-
logger.log(Level.SEVERE, "Could not compare trees", e);
267-
}
230+
if (parent instanceof ConstantCaseLabelTree constantCaseLabel
231+
&& tree.equals(constantCaseLabel.getConstantExpression())) {
232+
return null;
268233
}
269234
}
270235
if (sym.owner.equals(owner) && unit.starImportScope.includes(sym)) {

core/src/main/java/com/google/errorprone/bugpatterns/checkreturnvalue/ApiFactory.java

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import com.sun.tools.javac.code.Type.StructuralTypeMapping;
2424
import com.sun.tools.javac.code.TypeMetadata;
2525
import com.sun.tools.javac.code.Types;
26-
import java.lang.reflect.Method;
2726

2827
/** Utility method to produce {@link Api} objects from javac {@link MethodSymbol}. */
2928
public final class ApiFactory {
@@ -59,29 +58,18 @@ public Type visitType(Type t, Void unused) {
5958

6059
@Override
6160
public Type visitClassType(Type.ClassType t, Void unused) {
62-
return super.visitClassType((Type.ClassType) cloneWithoutMetadata(t), null);
61+
return super.visitClassType((Type.ClassType) dropAnnotations(t), null);
6362
}
6463

6564
// Remove annotations from all enclosing containers
6665
@Override
6766
public Type visitArrayType(Type.ArrayType t, Void unused) {
68-
return super.visitArrayType((Type.ArrayType) cloneWithoutMetadata(t), null);
67+
return super.visitArrayType((Type.ArrayType) dropAnnotations(t), null);
6968
}
7069
};
7170

72-
public static Type cloneWithoutMetadata(Type type) {
73-
try {
74-
try {
75-
Method method = Type.class.getMethod("cloneWithMetadata", TypeMetadata.class);
76-
return (Type) method.invoke(type, TypeMetadata.class.getField("EMPTY").get(null));
77-
} catch (NoSuchMethodException e) {
78-
Class<?> annotations = Class.forName("com.sun.tools.javac.code.TypeMetadata$Annotations");
79-
Method method = Type.class.getMethod("dropMetadata", Class.class);
80-
return (Type) method.invoke(type, annotations);
81-
}
82-
} catch (ReflectiveOperationException e) {
83-
throw new LinkageError(e.getMessage(), e);
84-
}
71+
public static Type dropAnnotations(Type type) {
72+
return type.dropMetadata(TypeMetadata.Annotations.class);
8573
}
8674

8775
private ApiFactory() {}

core/src/main/java/com/google/errorprone/refaster/ImportPolicy.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import com.google.common.collect.ImmutableSet;
2727
import com.google.common.collect.Iterables;
2828
import com.google.common.collect.Streams;
29+
import com.sun.source.tree.CompilationUnitTree;
30+
import com.sun.source.tree.ImportTree;
2931
import com.sun.tools.javac.code.Symbol.PackageSymbol;
3032
import com.sun.tools.javac.tree.JCTree;
3133
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
@@ -288,15 +290,13 @@ private static ImmutableSet<String> getAllImports(Inliner inliner, WhichImports
288290
.collect(toImmutableSet());
289291
}
290292

291-
@SuppressWarnings("unchecked")
292-
private static Collection<JCTree> getImports(JCCompilationUnit unit) {
293-
try {
294-
return (Collection<JCTree>) JCCompilationUnit.class.getMethod("getImports").invoke(unit);
295-
} catch (ReflectiveOperationException e) {
296-
throw new LinkageError(e.getMessage(), e);
297-
}
293+
// The return type of JCCompilationUnit#getImports changed for 'import module' in JDK 23
294+
@SuppressWarnings("UnnecessaryCast")
295+
private static List<? extends ImportTree> getImports(JCCompilationUnit unit) {
296+
return ((CompilationUnitTree) unit).getImports();
298297
}
299298

299+
// Added for 'module import' declarations in JDK 23
300300
private static JCTree getQualifiedIdentifier(JCImport i) {
301301
try {
302302
return (JCTree) JCImport.class.getMethod("getQualifiedIdentifier").invoke(i);

core/src/main/java/com/google/errorprone/refaster/PlaceholderUnificationVisitor.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -533,9 +533,7 @@ public Choice<State<JCEnhancedForLoop>> visitEnhancedForLoop(
533533
state,
534534
s -> unifyExpression(node.getExpression(), s),
535535
s -> unifyStatement(node.getStatement(), s),
536-
(expr, stmt) ->
537-
UEnhancedForLoop.makeForeachLoop(
538-
maker(), (JCVariableDecl) node.getVariable(), expr, stmt));
536+
(expr, stmt) -> maker().ForeachLoop((JCVariableDecl) node.getVariable(), expr, stmt));
539537
}
540538

541539
@Override

core/src/main/java/com/google/errorprone/refaster/UEnhancedForLoop.java

Lines changed: 7 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,10 @@
1919
import static com.google.errorprone.refaster.Unifier.unifications;
2020

2121
import com.google.auto.value.AutoValue;
22-
import com.google.common.base.VerifyException;
2322
import com.sun.source.tree.EnhancedForLoopTree;
2423
import com.sun.source.tree.Tree;
2524
import com.sun.source.tree.TreeVisitor;
26-
import com.sun.tools.javac.tree.JCTree;
2725
import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop;
28-
import com.sun.tools.javac.tree.JCTree.JCExpression;
29-
import com.sun.tools.javac.tree.JCTree.JCStatement;
30-
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
31-
import com.sun.tools.javac.tree.TreeMaker;
32-
import java.lang.reflect.Method;
33-
import java.util.Arrays;
3426

3527
/**
3628
* A {@link UTree} representation of a {@link EnhancedForLoopTree}.
@@ -44,63 +36,7 @@ abstract class UEnhancedForLoop extends USimpleStatement implements EnhancedForL
4436

4537
public static UEnhancedForLoop create(
4638
UVariableDecl variable, UExpression elements, UStatement statement) {
47-
// On JDK 20 and above the `EnhancedForLoopTree` interface contains a additional method
48-
// `getDeclarationKind()`, referencing a type not available prior to JDK 20. AutoValue
49-
// generates a corresponding field and accessor for this property. Here we find and invoke the
50-
// generated constructor with the appropriate arguments, depending on context.
51-
// See https://github.com/openjdk/jdk20/commit/2cb64a75578ccc15a1dfc8c2843aa11d05ca8aa7.
52-
// TODO: Simplify this logic once JDK 19 and older are no longer supported.
53-
return isCompiledWithJdk20Plus()
54-
? createJdk20PlusEnhancedForLoop(variable, elements, statement)
55-
: createPreJdk20EnhancedForLoop(variable, elements, statement);
56-
}
57-
58-
private static boolean isCompiledWithJdk20Plus() {
59-
return Arrays.stream(AutoValue_UEnhancedForLoop.class.getDeclaredMethods())
60-
.anyMatch(m -> "getDeclarationKind".equals(m.getName()));
61-
}
62-
63-
private static UEnhancedForLoop createPreJdk20EnhancedForLoop(
64-
UVariableDecl variable, UExpression elements, UStatement statement) {
65-
try {
66-
return AutoValue_UEnhancedForLoop.class
67-
.getDeclaredConstructor(UVariableDecl.class, UExpression.class, USimpleStatement.class)
68-
.newInstance(variable, elements, statement);
69-
} catch (ReflectiveOperationException e) {
70-
throw new LinkageError(e.getMessage(), e);
71-
}
72-
}
73-
74-
private static UEnhancedForLoop createJdk20PlusEnhancedForLoop(
75-
UVariableDecl variable, UExpression elements, UStatement statement) {
76-
Object declarationKind = getVariableDeclarationKind();
77-
try {
78-
return AutoValue_UEnhancedForLoop.class
79-
.getDeclaredConstructor(
80-
declarationKind.getClass(),
81-
UVariableDecl.class,
82-
UExpression.class,
83-
USimpleStatement.class)
84-
.newInstance(declarationKind, variable, elements, statement);
85-
} catch (ReflectiveOperationException e) {
86-
throw new LinkageError(e.getMessage(), e);
87-
}
88-
}
89-
90-
private static Object getVariableDeclarationKind() {
91-
Class<?> declarationKind;
92-
try {
93-
declarationKind = Class.forName("com.sun.source.tree.EnhancedForLoopTree$DeclarationKind");
94-
} catch (ClassNotFoundException e) {
95-
throw new VerifyException("Cannot load `EnhancedForLoopTree.DeclarationKind` enum", e);
96-
}
97-
return Arrays.stream(declarationKind.getEnumConstants())
98-
.filter(v -> "VARIABLE".equals(v.toString()))
99-
.findFirst()
100-
.orElseThrow(
101-
() ->
102-
new VerifyException(
103-
"Enum value `EnhancedForLoopTree.DeclarationKind.VARIABLE` not found"));
39+
return new AutoValue_UEnhancedForLoop(variable, elements, (USimpleStatement) statement);
10440
}
10541

10642
@Override
@@ -129,38 +65,12 @@ public Kind getKind() {
12965

13066
@Override
13167
public JCEnhancedForLoop inline(Inliner inliner) throws CouldNotResolveImportException {
132-
return makeForeachLoop(
133-
inliner.maker(),
134-
getVariable().inline(inliner),
135-
getExpression().inline(inliner),
136-
getStatement().inline(inliner));
137-
}
138-
139-
private static final Method treeMakerForeachLoopMethod = treeMakerForeachLoopMethod();
140-
141-
private static Method treeMakerForeachLoopMethod() {
142-
try {
143-
return TreeMaker.class.getMethod(
144-
"ForeachLoop", JCTree.class, JCExpression.class, JCStatement.class);
145-
} catch (ReflectiveOperationException e1) {
146-
try {
147-
return TreeMaker.class.getMethod(
148-
"ForeachLoop", JCVariableDecl.class, JCExpression.class, JCStatement.class);
149-
} catch (ReflectiveOperationException e2) {
150-
e2.addSuppressed(e1);
151-
throw new LinkageError(e2.getMessage(), e2);
152-
}
153-
}
154-
}
155-
156-
static JCEnhancedForLoop makeForeachLoop(
157-
TreeMaker maker, JCVariableDecl variable, JCExpression expression, JCStatement statement) {
158-
try {
159-
return (JCEnhancedForLoop)
160-
treeMakerForeachLoopMethod.invoke(maker, variable, expression, statement);
161-
} catch (ReflectiveOperationException e) {
162-
throw new LinkageError(e.getMessage(), e);
163-
}
68+
return inliner
69+
.maker()
70+
.ForeachLoop(
71+
getVariable().inline(inliner),
72+
getExpression().inline(inliner),
73+
getStatement().inline(inliner));
16474
}
16575

16676
@Override

0 commit comments

Comments
 (0)