Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static com.google.errorprone.matchers.Matchers.annotations;
import static com.google.errorprone.matchers.ProtobufMatchers.MESSAGE_LITE_TYPE;
import static com.google.errorprone.util.ASTHelpers.getSymbol;
import static com.google.errorprone.util.ASTHelpers.hasExplicitSource;
import static com.google.errorprone.util.ASTHelpers.isSubtype;

import com.google.common.collect.ImmutableSet;
Expand Down Expand Up @@ -275,6 +276,15 @@ private void moveTypeAnnotations(
SuggestedFix.Builder builder) {
for (AnnotationTree annotation :
HAS_TYPE_USE_ANNOTATION.multiMatchResult(annotationHolder, state).matchingNodes()) {
if (!hasExplicitSource(annotation, state)) {
// A record component's type-use annotation can be reached through javac's
// synthesized members (field/accessor/canonical constructor), whose copy of the
// annotation tree has no recorded end position. Deleting and reinserting it would
// build an invalid Replacement and crash the whole compilation (#6074). Leave the
// annotation where it is -- the node is still qualified by the prefixWith() call
// above, it just won't be relocated ahead of the qualified type.
continue;
}
builder.delete(annotation);
builder.prefixWith(node, state.getSourceForNode(annotation) + " ");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,53 @@ abstract class Test {
.doTest();
}


@Test
public void recordComponentWithTypeUseAnnotation_doesNotCrash() {
refactoringTestHelper
.addInputLines(
"input/TypeUseAnnotation.java",
"""
package test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target(ElementType.TYPE_USE)
@interface TypeUseAnnotation {}
""")
.expectUnchanged()
.addInputLines(
"input/SomeClass.java",
"""
package test;

class SomeClass {
enum Builder {
A
}
}
""")
.expectUnchanged()
.addInputLines(
"input/Test.java",
"""
package test;

import test.SomeClass.Builder;

record Test(@TypeUseAnnotation Builder builder) {}
""")
.addOutputLines(
"output/Test.java",
"""
package test;

record Test(@TypeUseAnnotation SomeClass.Builder builder) {}
""")
.doTest();
}

@Test
public void negative_truth8AssertThatFalseFlag() {
compilationTestHelper
Expand Down