diff --git a/check_api/src/main/java/com/google/errorprone/JavacErrorDescriptionListener.java b/check_api/src/main/java/com/google/errorprone/JavacErrorDescriptionListener.java index 5c29d9e76c4..05955df3214 100644 --- a/check_api/src/main/java/com/google/errorprone/JavacErrorDescriptionListener.java +++ b/check_api/src/main/java/com/google/errorprone/JavacErrorDescriptionListener.java @@ -22,10 +22,10 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.errorprone.fixes.AppliedFix; +import com.google.errorprone.fixes.ErrorProneEndPosTable; import com.google.errorprone.fixes.Fix; import com.google.errorprone.matchers.Description; import com.sun.source.tree.ImportTree; -import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.JCDiagnostic; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -68,7 +68,7 @@ public class JavacErrorDescriptionListener implements DescriptionListener { private JavacErrorDescriptionListener( Log log, - EndPosTable endPositions, + ErrorProneEndPosTable endPositions, JavaFileObject sourceFile, Context context, boolean dontUseErrors) { @@ -169,12 +169,20 @@ private static String messageForFixes(Description description, List static Factory provider(Context context) { return (log, compilation) -> new JavacErrorDescriptionListener( - log, compilation.endPositions, compilation.getSourceFile(), context, false); + log, + ErrorProneEndPosTable.create(compilation), + compilation.getSourceFile(), + context, + false); } static Factory providerForRefactoring(Context context) { return (log, compilation) -> new JavacErrorDescriptionListener( - log, compilation.endPositions, compilation.getSourceFile(), context, true); + log, + ErrorProneEndPosTable.create(compilation), + compilation.getSourceFile(), + context, + true); } } diff --git a/check_api/src/main/java/com/google/errorprone/apply/DescriptionBasedDiff.java b/check_api/src/main/java/com/google/errorprone/apply/DescriptionBasedDiff.java index 3d60e808b5e..d0d942d6fa8 100644 --- a/check_api/src/main/java/com/google/errorprone/apply/DescriptionBasedDiff.java +++ b/check_api/src/main/java/com/google/errorprone/apply/DescriptionBasedDiff.java @@ -19,11 +19,11 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.errorprone.DescriptionListener; +import com.google.errorprone.fixes.ErrorProneEndPosTable; import com.google.errorprone.fixes.Fix; import com.google.errorprone.fixes.Replacement; import com.google.errorprone.fixes.Replacements; import com.google.errorprone.matchers.Description; -import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import java.net.URI; import java.nio.file.Paths; @@ -46,7 +46,7 @@ public final class DescriptionBasedDiff implements DescriptionListener, Diff { private final JCCompilationUnit compilationUnit; private final Set importsToAdd; private final Set importsToRemove; - private final EndPosTable endPositions; + private final ErrorProneEndPosTable endPositions; private final Replacements replacements = new Replacements(); private final ImportOrganizer importOrganizer; @@ -73,7 +73,7 @@ private DescriptionBasedDiff( this.ignoreOverlappingFixes = ignoreOverlappingFixes; this.importsToAdd = new LinkedHashSet<>(); this.importsToRemove = new LinkedHashSet<>(); - this.endPositions = compilationUnit.endPositions; + this.endPositions = ErrorProneEndPosTable.create(compilationUnit); this.importOrganizer = importOrganizer; } diff --git a/check_api/src/main/java/com/google/errorprone/apply/ImportStatements.java b/check_api/src/main/java/com/google/errorprone/apply/ImportStatements.java index 7849e096233..4b6f20c36da 100644 --- a/check_api/src/main/java/com/google/errorprone/apply/ImportStatements.java +++ b/check_api/src/main/java/com/google/errorprone/apply/ImportStatements.java @@ -16,12 +16,13 @@ package com.google.errorprone.apply; +import static com.google.errorprone.fixes.ErrorProneEndPosTable.getEndPosition; + import com.google.common.base.CharMatcher; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.errorprone.annotations.CanIgnoreReturnValue; -import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCExpression; @@ -58,31 +59,29 @@ public static ImportStatements create( return new ImportStatements( (JCExpression) compilationUnit.getPackageName(), compilationUnit.getImports(), - compilationUnit.endPositions, + compilationUnit, importOrganizer); } ImportStatements( JCExpression packageTree, List importTrees, - EndPosTable endPositions, + JCCompilationUnit unit, ImportOrganizer importOrganizer) { // find start, end positions for current list of imports (for replacement) if (importTrees.isEmpty()) { // start/end positions are just after the package expression hasExistingImports = false; - startPos = - packageTree != null - ? packageTree.getEndPosition(endPositions) + 2 // +2 for semicolon and newline - : 0; + // +2 for semicolon and newline + startPos = packageTree != null ? getEndPosition(packageTree, unit) + 2 : 0; endPos = startPos; } else { // process list of imports and find start/end positions hasExistingImports = true; for (JCTree importTree : importTrees) { int currStartPos = importTree.getStartPosition(); - int currEndPos = importTree.getEndPosition(endPositions); + int currEndPos = getEndPosition(importTree, unit); startPos = Math.min(startPos, currStartPos); endPos = Math.max(endPos, currEndPos); diff --git a/check_api/src/main/java/com/google/errorprone/fixes/AdjustedPosition.java b/check_api/src/main/java/com/google/errorprone/fixes/AdjustedPosition.java index 0ee0df90d74..c7a79d6ad18 100644 --- a/check_api/src/main/java/com/google/errorprone/fixes/AdjustedPosition.java +++ b/check_api/src/main/java/com/google/errorprone/fixes/AdjustedPosition.java @@ -18,10 +18,9 @@ import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; /** Describes a tree position with adjustments to the start and end indices. */ -public class AdjustedPosition implements DiagnosticPosition { +public class AdjustedPosition implements ErrorPronePosition { protected final JCTree position; protected final int startPositionAdjustment; protected final int endPositionAdjustment; @@ -51,4 +50,9 @@ public int getPreferredPosition() { public int getEndPosition(EndPosTable endPositions) { return position.getEndPosition(endPositions) + endPositionAdjustment; } + + @Override + public int getEndPosition(ErrorProneEndPosTable endPositions) { + return endPositions.getEndPosition(position) + endPositionAdjustment; + } } diff --git a/check_api/src/main/java/com/google/errorprone/fixes/AppliedFix.java b/check_api/src/main/java/com/google/errorprone/fixes/AppliedFix.java index 827bdbff446..38d0b65b456 100644 --- a/check_api/src/main/java/com/google/errorprone/fixes/AppliedFix.java +++ b/check_api/src/main/java/com/google/errorprone/fixes/AppliedFix.java @@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Range; -import com.sun.tools.javac.tree.EndPosTable; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -39,7 +38,7 @@ public record AppliedFix(String snippet, boolean isRemoveLine) { * to the source, or a change only to imports. */ public static @Nullable AppliedFix apply( - CharSequence source, EndPosTable endPositions, Fix suggestedFix) { + CharSequence source, ErrorProneEndPosTable endPositions, Fix suggestedFix) { // We apply the replacements in ascending order here. Descending is simpler, since applying a // replacement can't change the index for future replacements, but it leads to quadratic // copying behavior as we constantly shift the tail of the file around in our StringBuilder. @@ -91,7 +90,8 @@ private static String snippet( return firstEditedLine(replaced, shiftedReplacements.getFirst()); } - public static String applyReplacements(CharSequence source, EndPosTable endPositions, Fix fix) { + public static String applyReplacements( + CharSequence source, ErrorProneEndPosTable endPositions, Fix fix) { return applyReplacements(source, fix.getReplacements(endPositions)); } diff --git a/check_api/src/main/java/com/google/errorprone/fixes/ErrorProneEndPosTable.java b/check_api/src/main/java/com/google/errorprone/fixes/ErrorProneEndPosTable.java new file mode 100644 index 00000000000..f7a1f064219 --- /dev/null +++ b/check_api/src/main/java/com/google/errorprone/fixes/ErrorProneEndPosTable.java @@ -0,0 +1,58 @@ +/* + * Copyright 2025 The Error Prone Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.errorprone.fixes; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.Tree; +import com.sun.tools.javac.tree.EndPosTable; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.util.JCDiagnostic; + +/** A compatibility wrapper around {@link EndPosTable}. */ +public interface ErrorProneEndPosTable { + + static ErrorProneEndPosTable create(CompilationUnitTree unit) { + EndPosTable endPosTable = ((JCTree.JCCompilationUnit) unit).endPositions; + return pos -> pos.getEndPosition(endPosTable); + } + + static ErrorProneEndPosTable create(EndPosTable endPosTable) { + return pos -> pos.getEndPosition(endPosTable); + } + + default int getEndPosition(Tree tree) { + return getEndPosition((JCDiagnostic.DiagnosticPosition) tree); + } + + default int getEndPosition(JCTree tree) { + return getEndPosition((JCDiagnostic.DiagnosticPosition) tree); + } + + int getEndPosition(JCDiagnostic.DiagnosticPosition pos); + + static int getEndPosition(Tree tree, CompilationUnitTree unit) { + return getEndPosition((JCDiagnostic.DiagnosticPosition) tree, unit); + } + + static int getEndPosition(JCTree tree, CompilationUnitTree unit) { + return getEndPosition((JCDiagnostic.DiagnosticPosition) tree, unit); + } + + static int getEndPosition(JCDiagnostic.DiagnosticPosition pos, CompilationUnitTree unit) { + return create(unit).getEndPosition(pos); + } +} diff --git a/check_api/src/main/java/com/google/errorprone/fixes/ErrorPronePosition.java b/check_api/src/main/java/com/google/errorprone/fixes/ErrorPronePosition.java new file mode 100644 index 00000000000..67662067f5f --- /dev/null +++ b/check_api/src/main/java/com/google/errorprone/fixes/ErrorPronePosition.java @@ -0,0 +1,57 @@ +/* + * Copyright 2025 The Error Prone Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.errorprone.fixes; + +import com.sun.source.tree.Tree; +import com.sun.tools.javac.tree.EndPosTable; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; + +/** A compatibility wrapper around {@link DiagnosticPosition}. */ +public interface ErrorPronePosition extends DiagnosticPosition { + static ErrorPronePosition from(Tree node) { + DiagnosticPosition pos = (DiagnosticPosition) node; + return new ErrorPronePosition() { + @Override + public int getStartPosition() { + return pos.getStartPosition(); + } + + @Override + public int getPreferredPosition() { + return pos.getPreferredPosition(); + } + + @Override + public JCTree getTree() { + return pos.getTree(); + } + + @Override + public int getEndPosition(EndPosTable endPosTable) { + return pos.getEndPosition(endPosTable); + } + + @Override + public int getEndPosition(ErrorProneEndPosTable endPosTable) { + return endPosTable.getEndPosition(pos); + } + }; + } + + int getEndPosition(ErrorProneEndPosTable endPosTable); +} diff --git a/check_api/src/main/java/com/google/errorprone/fixes/Fix.java b/check_api/src/main/java/com/google/errorprone/fixes/Fix.java index 2a1f2100b47..449f4ed58cc 100644 --- a/check_api/src/main/java/com/google/errorprone/fixes/Fix.java +++ b/check_api/src/main/java/com/google/errorprone/fixes/Fix.java @@ -39,7 +39,15 @@ public interface Fix { Replacements.CoalescePolicy getCoalescePolicy(); - ImmutableSet getReplacements(EndPosTable endPositions); + ImmutableSet getReplacements(ErrorProneEndPosTable endPositions); + + /** + * @deprecated use {@link #getReplacements(ErrorProneEndPosTable) instead} + */ + @Deprecated + default ImmutableSet getReplacements(EndPosTable endPositions) { + return getReplacements(ErrorProneEndPosTable.create(endPositions)); + } ImmutableSet getImportsToAdd(); diff --git a/check_api/src/main/java/com/google/errorprone/fixes/FixedPosition.java b/check_api/src/main/java/com/google/errorprone/fixes/FixedPosition.java index 14d1564bc38..71f4c1427e8 100644 --- a/check_api/src/main/java/com/google/errorprone/fixes/FixedPosition.java +++ b/check_api/src/main/java/com/google/errorprone/fixes/FixedPosition.java @@ -22,7 +22,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; /** A {@link DiagnosticPosition} with a fixed position. */ -public final class FixedPosition implements DiagnosticPosition { +public final class FixedPosition implements ErrorPronePosition { private final JCTree tree; private final int startPosition; @@ -46,6 +46,11 @@ public int getPreferredPosition() { return startPosition; } + @Override + public int getEndPosition(ErrorProneEndPosTable endPosTable) { + return startPosition; + } + @Override public int getEndPosition(EndPosTable endPosTable) { return startPosition; diff --git a/check_api/src/main/java/com/google/errorprone/fixes/IndexedPosition.java b/check_api/src/main/java/com/google/errorprone/fixes/IndexedPosition.java index 2ed83d8cd25..e999fba1548 100644 --- a/check_api/src/main/java/com/google/errorprone/fixes/IndexedPosition.java +++ b/check_api/src/main/java/com/google/errorprone/fixes/IndexedPosition.java @@ -20,10 +20,9 @@ import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; /** Describes a position that only has a start and end index. */ -public class IndexedPosition implements DiagnosticPosition { +public class IndexedPosition implements ErrorPronePosition { final int startPos; final int endPos; @@ -50,6 +49,11 @@ public int getPreferredPosition() { throw new UnsupportedOperationException(); } + @Override + public int getEndPosition(ErrorProneEndPosTable endPosTable) { + return endPos; + } + @Override public int getEndPosition(EndPosTable endPosTable) { return endPos; diff --git a/check_api/src/main/java/com/google/errorprone/fixes/SuggestedFix.java b/check_api/src/main/java/com/google/errorprone/fixes/SuggestedFix.java index 0a313491f99..347c3330cdd 100644 --- a/check_api/src/main/java/com/google/errorprone/fixes/SuggestedFix.java +++ b/check_api/src/main/java/com/google/errorprone/fixes/SuggestedFix.java @@ -28,7 +28,6 @@ import com.google.errorprone.util.ASTHelpers; import com.sun.source.tree.MethodTree; import com.sun.source.tree.Tree; -import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -70,7 +69,7 @@ public boolean isEmpty() { @Override public String toString(JCCompilationUnit compilationUnit) { StringBuilder result = new StringBuilder("replace "); - for (Replacement replacement : getReplacements(compilationUnit.endPositions)) { + for (Replacement replacement : getReplacements(ErrorProneEndPosTable.create(compilationUnit))) { result.append( String.format( "position %d:%d with \"%s\" ", @@ -87,7 +86,7 @@ public String toString(JCCompilationUnit compilationUnit) { public abstract int hashCode(); @Override - public ImmutableSet getReplacements(EndPosTable endPositions) { + public ImmutableSet getReplacements(ErrorProneEndPosTable endPositions) { if (endPositions == null) { throw new IllegalArgumentException( "Cannot produce correct replacements without endPositions."); @@ -229,7 +228,7 @@ public Builder setCoalescePolicy(CoalescePolicy coalescePolicy) { @CanIgnoreReturnValue public Builder replace(Tree node, String replaceWith) { checkNotSyntheticConstructor(node); - return with(ReplacementFix.create((DiagnosticPosition) node, replaceWith)); + return with(ReplacementFix.create(ErrorPronePosition.from(node), replaceWith)); } /** @@ -242,7 +241,7 @@ public Builder replace(Tree node, String replaceWith) { */ @CanIgnoreReturnValue public Builder replace(int startPos, int endPos, String replaceWith) { - DiagnosticPosition pos = new IndexedPosition(startPos, endPos); + IndexedPosition pos = new IndexedPosition(startPos, endPos); return with(ReplacementFix.create(pos, replaceWith)); } @@ -292,8 +291,10 @@ public Builder delete(Tree node) { public Builder swap(Tree node1, Tree node2, VisitorState state) { checkNotSyntheticConstructor(node1); checkNotSyntheticConstructor(node2); - fixes.add(ReplacementFix.create((DiagnosticPosition) node1, state.getSourceForNode(node2))); - fixes.add(ReplacementFix.create((DiagnosticPosition) node2, state.getSourceForNode(node1))); + fixes.add( + ReplacementFix.create(ErrorPronePosition.from(node1), state.getSourceForNode(node2))); + fixes.add( + ReplacementFix.create(ErrorPronePosition.from(node2), state.getSourceForNode(node1))); return this; } @@ -385,19 +386,19 @@ private static void checkNotSyntheticConstructor(Tree tree) { /** Models a single fix operation. */ interface FixOperation { /** Calculate the replacement operation once end positions are available. */ - Replacement getReplacement(EndPosTable endPositions); + Replacement getReplacement(ErrorProneEndPosTable endPositions); } /** Inserts new text at a specific insertion point (e.g. prefix or postfix). */ abstract static class InsertionFix implements FixOperation { - protected abstract int getInsertionIndex(EndPosTable endPositions); + protected abstract int getInsertionIndex(ErrorProneEndPosTable endPositions); protected abstract DiagnosticPosition position(); protected abstract String insertion(); @Override - public Replacement getReplacement(EndPosTable endPositions) { + public Replacement getReplacement(ErrorProneEndPosTable endPositions) { int insertionIndex = getInsertionIndex(endPositions); return Replacement.create(insertionIndex, insertionIndex, insertion()); } @@ -412,8 +413,8 @@ public static PostfixInsertion create(DiagnosticPosition position, String insert } @Override - protected int getInsertionIndex(EndPosTable endPositions) { - return position().getEndPosition(endPositions); + protected int getInsertionIndex(ErrorProneEndPosTable endPositions) { + return endPositions.getEndPosition(position()); } } @@ -426,24 +427,24 @@ public static PrefixInsertion create(DiagnosticPosition position, String inserti } @Override - protected int getInsertionIndex(EndPosTable endPositions) { + protected int getInsertionIndex(ErrorProneEndPosTable endPositions) { return position().getStartPosition(); } } /** Replaces an entire diagnostic position (from start to end) with the given string. */ - private record ReplacementFix(DiagnosticPosition original, String replacement) + private record ReplacementFix(ErrorPronePosition original, String replacement) implements FixOperation { ReplacementFix { checkArgument(original.getStartPosition() >= 0, "invalid start position"); } - static ReplacementFix create(DiagnosticPosition original, String replacement) { + static ReplacementFix create(ErrorPronePosition original, String replacement) { return new ReplacementFix(original, replacement); } @Override - public Replacement getReplacement(EndPosTable endPositions) { + public Replacement getReplacement(ErrorProneEndPosTable endPositions) { return Replacement.create( original().getStartPosition(), original().getEndPosition(endPositions), replacement()); } diff --git a/check_api/src/main/java/com/google/errorprone/fixes/SuggestedFixes.java b/check_api/src/main/java/com/google/errorprone/fixes/SuggestedFixes.java index a329903b08d..f123a93dbc7 100644 --- a/check_api/src/main/java/com/google/errorprone/fixes/SuggestedFixes.java +++ b/check_api/src/main/java/com/google/errorprone/fixes/SuggestedFixes.java @@ -22,6 +22,7 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.Iterables.getLast; import static com.google.common.collect.Streams.stream; +import static com.google.errorprone.fixes.ErrorProneEndPosTable.getEndPosition; import static com.google.errorprone.util.ASTHelpers.getAnnotation; import static com.google.errorprone.util.ASTHelpers.getAnnotationWithSimpleName; import static com.google.errorprone.util.ASTHelpers.getModifiers; @@ -98,7 +99,6 @@ import com.sun.tools.javac.parser.Tokens.TokenKind; import com.sun.tools.javac.tree.DCTree; import com.sun.tools.javac.tree.DCTree.DCDocComment; -import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.util.Context; @@ -497,9 +497,7 @@ public static void replaceDocTree( private static int endPosition( DCTree.DCEndPosTree node, DCTree.DCDocComment comment, DocTreePath docPath) { JCDiagnostic.DiagnosticPosition pos = node.pos(comment); - EndPosTable endPositions = - ((JCCompilationUnit) docPath.getTreePath().getCompilationUnit()).endPositions; - return pos.getEndPosition(endPositions); + return getEndPosition(pos, docPath.getTreePath().getCompilationUnit()); } /** diff --git a/check_api/src/test/java/com/google/errorprone/fixes/AppliedFixTest.java b/check_api/src/test/java/com/google/errorprone/fixes/AppliedFixTest.java index 5c0e5e890c6..ad4b066f202 100644 --- a/check_api/src/test/java/com/google/errorprone/fixes/AppliedFixTest.java +++ b/check_api/src/test/java/com/google/errorprone/fixes/AppliedFixTest.java @@ -18,7 +18,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -30,6 +29,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.ArgumentMatchers; /** * @author alexeagle@google.com (Alex Eagle) @@ -39,14 +39,15 @@ public class AppliedFixTest { // This is unused by the test, it just needs to be non-null. // The proxy is necessary since the interface contains breaking changes across JDK versions. - final EndPosTable endPositions = - (EndPosTable) - Proxy.newProxyInstance( - AppliedFixTest.class.getClassLoader(), - new Class[] {EndPosTable.class}, - (proxy, method, args) -> { - throw new UnsupportedOperationException(); - }); + final ErrorProneEndPosTable endPositions = + ErrorProneEndPosTable.create( + (EndPosTable) + Proxy.newProxyInstance( + AppliedFixTest.class.getClassLoader(), + new Class[] {EndPosTable.class}, + (proxy, method, args) -> { + throw new UnsupportedOperationException(); + })); // TODO(b/67738557): consolidate helpers for creating fake trees JCTree node(int startPos, int endPos) { @@ -152,7 +153,8 @@ public void shouldApplyFixesInReverseOrder() { ImmutableSet.of(Replacement.create(0, 1, ""), Replacement.create(1, 1, "")); Fix mockFix = mock(Fix.class); - when(mockFix.getReplacements(any())).thenReturn(replacements); + when(mockFix.getReplacements(ArgumentMatchers.any())) + .thenReturn(replacements); // If the fixes had been applied in the wrong order, this would fail. // But it succeeds, so they were applied in the right order. diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClass.java b/core/src/main/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClass.java index ff055d1ec79..86aa0ce04c3 100644 --- a/core/src/main/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClass.java +++ b/core/src/main/java/com/google/errorprone/bugpatterns/UnnecessaryAnonymousClass.java @@ -36,6 +36,7 @@ import com.google.errorprone.BugPattern; import com.google.errorprone.VisitorState; import com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher; +import com.google.errorprone.fixes.ErrorProneEndPosTable; import com.google.errorprone.fixes.Replacement; import com.google.errorprone.fixes.SuggestedFix; import com.google.errorprone.fixes.SuggestedFixes; @@ -54,7 +55,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.tree.JCTree.JCCompilationUnit; import java.util.Objects; import java.util.Optional; import javax.lang.model.element.ElementKind; @@ -180,7 +180,7 @@ private static SuggestedFix ensureFixesDoNotOverlap( SuggestedFix.Builder fixBuilder = SuggestedFix.builder(); // Apply each fix generated by ReplaceUsesScanner to fixBuilder. for (Replacement replacement : - fix.getReplacements(((JCCompilationUnit) compilationUnit).endPositions)) { + fix.getReplacements(ErrorProneEndPosTable.create(compilationUnit))) { if (replacement.range().isConnected(methodBodyPositionRange)) { // If the usage replacement overlaps with the method body, apply it to the method body // source directly, to avoid fix collisions when we replace the whole thing. diff --git a/core/src/main/java/com/google/errorprone/bugpatterns/inlineme/Inliner.java b/core/src/main/java/com/google/errorprone/bugpatterns/inlineme/Inliner.java index 2237412cee4..f9410a2a146 100644 --- a/core/src/main/java/com/google/errorprone/bugpatterns/inlineme/Inliner.java +++ b/core/src/main/java/com/google/errorprone/bugpatterns/inlineme/Inliner.java @@ -45,6 +45,7 @@ import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher; import com.google.errorprone.bugpatterns.BugChecker.NewClassTreeMatcher; import com.google.errorprone.fixes.AppliedFix; +import com.google.errorprone.fixes.ErrorProneEndPosTable; import com.google.errorprone.fixes.SuggestedFix; import com.google.errorprone.fixes.SuggestedFixes; import com.google.errorprone.matchers.Description; @@ -67,9 +68,7 @@ import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.parser.JavacParser; import com.sun.tools.javac.parser.ParserFactory; -import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree; -import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -572,15 +571,7 @@ private boolean matchesApiPrefixes(Api api) { return false; } - private static EndPosTable asEndPosTable(JavacParser parser) { - return (EndPosTable) - Proxy.newProxyInstance( - EndPosTable.class.getClassLoader(), - new Class[] {EndPosTable.class}, - (proxy, method, args) -> - switch (method.getName()) { - case "getEndPos" -> parser.getEndPos((JCTree) args[0]); - default -> throw new AssertionError("Unexpected method: " + method.getName()); - }); + private static ErrorProneEndPosTable asEndPosTable(JavacParser parser) { + return tree -> parser.getEndPos((JCTree) tree); } }