Skip to content

Commit

Permalink
preserve annotation values when parsing compiled classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Eason Lin committed Dec 4, 2024
1 parent efc38e3 commit 334b9e2
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,10 @@ private void completeClassSymbol(Symbol.ClassSymbol classSymbol) {
if (retention != null && retention.value() == RetentionPolicy.SOURCE) {
continue;
}
annotations.add(annotType);
List<JavaType.AnnotationValue> annotationValues = a.values.stream().map(attr -> new JavaType.AnnotationValue(
methodDeclarationType(attr.fst, annotType), attr.snd.getValue().toString())).toList();
JavaType.Annotation annotation = new JavaType.Annotation(annotType, annotationValues);
annotations.add(annotation);
}
}
return annotations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,10 @@ private void completeClassSymbol(Symbol.ClassSymbol classSymbol) {
if (retention != null && retention.value() == RetentionPolicy.SOURCE) {
continue;
}
annotations.add(annotType);
List<JavaType.AnnotationValue> annotationValues = a.values.stream().map(attr -> new JavaType.AnnotationValue(
methodDeclarationType(attr.fst, annotType), attr.snd.getValue().toString())).toList();
JavaType.Annotation annotation = new JavaType.Annotation(annotType, annotationValues);
annotations.add(annotation);
}
}
return annotations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,10 @@ private void completeClassSymbol(Symbol.ClassSymbol classSymbol) {
if (retention != null && retention.value() == RetentionPolicy.SOURCE) {
continue;
}
annotations.add(annotType);
List<JavaType.AnnotationValue> annotationValues = a.values.stream().map(attr -> new JavaType.AnnotationValue(
methodDeclarationType(attr.fst, annotType), attr.snd.getValue().toString())).toList();
JavaType.Annotation annotation = new JavaType.Annotation(annotType, annotationValues);
annotations.add(annotation);
}
}
return annotations;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@

import org.junit.jupiter.api.Test;
import org.openrewrite.InMemoryExecutionContext;
import org.openrewrite.SourceFile;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.test.RewriteTest;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class Java21ParserTest implements RewriteTest {

Expand All @@ -30,4 +37,46 @@ void shouldLoadResourceFromClasspath() throws IOException {
Files.deleteIfExists(Paths.get(System.getProperty("user.home"), ".rewrite", "classpath", "jackson-annotations-2.17.1.jar"));
rewriteRun(spec -> spec.parser(JavaParser.fromJavaVersion().classpathFromResources(new InMemoryExecutionContext(), "jackson-annotations")));
}

@Test
void testPreserveAnnotationsFromClasspath() throws IOException {
JavaParser p = JavaParser.fromJavaVersion().build();
/**
* Using these annotations in core library for testing this feature:
*
* @Deprecated(since="1.2", forRemoval=true)
* public final void stop()
*
* @CallerSensitive
* public ClassLoader getContextClassLoader() {
*/
List<SourceFile> sourceFiles = p.parse(
"""
class Test {
public void test() {
Thread.currentThread().stop();
Thread.currentThread().getContextClassLoader();
}
}
"""
).toList();
J.CompilationUnit cu = (J.CompilationUnit) sourceFiles.get(0);

J.MethodDeclaration md = (J.MethodDeclaration) cu.getClasses().get(0).getBody().getStatements().get(0);
J.MethodInvocation mi = (J.MethodInvocation) md.getBody().getStatements().get(0);
JavaType.Annotation annotation = (JavaType.Annotation) mi.getMethodType().getAnnotations().get(0);

// Thread.currentThread().stop();
assertEquals("java.lang.Deprecated" ,annotation.type.getFullyQualifiedName());
assertEquals("since", annotation.values.get(0).getMethod().getName());
assertEquals("1.2", annotation.values.get(0).getValue());
assertEquals("forRemoval", annotation.values.get(1).getMethod().getName());
assertEquals("true", annotation.values.get(1).getValue());

// Thread.currentThread().getContextClassLoader();
mi = (J.MethodInvocation) md.getBody().getStatements().get(1);
annotation = (JavaType.Annotation) mi.getMethodType().getAnnotations().get(0);
assertEquals("jdk.internal.reflect.CallerSensitive" ,annotation.type.getFullyQualifiedName());
assertTrue(annotation.values.isEmpty());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,10 @@ private void completeClassSymbol(Symbol.ClassSymbol classSymbol) {
if (retention != null && retention.value() == RetentionPolicy.SOURCE) {
continue;
}
annotations.add(annotType);
List<JavaType.AnnotationValue> annotationValues = a.values.stream().map(attr -> new JavaType.AnnotationValue(
methodDeclarationType(attr.fst, annotType), attr.snd.getValue().toString())).toList();
JavaType.Annotation annotation = new JavaType.Annotation(annotType, annotationValues);
annotations.add(annotation);
}
}
return annotations;
Expand Down
79 changes: 79 additions & 0 deletions rewrite-java/src/main/java/org/openrewrite/java/tree/JavaType.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.fasterxml.jackson.annotation.*;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.With;
import lombok.experimental.FieldDefaults;
Expand All @@ -26,6 +27,7 @@
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.internal.DefaultJavaTypeSignatureBuilder;

import java.lang.invoke.MethodType;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -626,6 +628,83 @@ public static ShallowClass build(String fullyQualifiedName) {
}
}

@Data
class AnnotationValue {
private final Method method;
private final String value;
}

class Annotation extends FullyQualified {

public final List<AnnotationValue> values;
public final FullyQualified type;

public Annotation(FullyQualified type, List<AnnotationValue> values) {
this.type = type;
this.values = values;
}

@Override
public String getFullyQualifiedName() {
return type.getFullyQualifiedName();
}

@Override
public FullyQualified withFullyQualifiedName(String fullyQualifiedName) {
return null;
}

@Override
public List<FullyQualified> getAnnotations() {
return type.getAnnotations();
}

@Override
public boolean hasFlags(Flag... test) {
return type.hasFlags();
}

@Override
public Set<Flag> getFlags() {
return type.getFlags();
}

@Override
public List<FullyQualified> getInterfaces() {
return type.getInterfaces();
}

@Override
public Kind getKind() {
return type.getKind();
}

@Override
public List<Variable> getMembers() {
return type.getMembers();
}

@Override
public List<Method> getMethods() {
return type.getMethods();
}

@Override
public List<JavaType> getTypeParameters() {
return type.getTypeParameters();
}

@Override
public @Nullable FullyQualified getOwningClass() {
return type.getOwningClass();
}

@Override
public @Nullable FullyQualified getSupertype() {
return type.getSupertype();
}
}

@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
class Parameterized extends FullyQualified {
@Getter
Expand Down

0 comments on commit 334b9e2

Please sign in to comment.