diff --git a/README.md b/README.md index d003dc9..9bd5d83 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ augments compiled classes with some additional data used by Datadog products. List of things that the plugin does: - Annotate every class with a `@SourcePath("...")` annotation that has the path to the class' source code -- Annotate every public method with a `@MethodLines("...")` annotation that has method start and end lines (taking into account method modifiers and annotations) +- Annotate every class, interface, enum and public method with a `@SourceLines("...")` annotation that has start and end lines (taking into account modifiers and annotations) ## Configuration @@ -29,7 +29,7 @@ Add plugin-client JAR to the project's classpath: com.datadoghq dd-javac-plugin-client - 0.2.0 + 0.2.2 ``` @@ -49,7 +49,7 @@ Add plugin JAR to the compiler's annotation processor path and pass the plugin a com.datadoghq dd-javac-plugin - 0.2.0 + 0.2.2 @@ -73,9 +73,9 @@ the plugin argument: ```groovy dependencies { - implementation 'com.datadoghq:dd-javac-plugin-client:0.2.0' - annotationProcessor 'com.datadoghq:dd-javac-plugin:0.2.0' - testAnnotationProcessor 'com.datadoghq:dd-javac-plugin:0.2.0' + implementation 'com.datadoghq:dd-javac-plugin-client:0.2.2' + annotationProcessor 'com.datadoghq:dd-javac-plugin:0.2.2' + testAnnotationProcessor 'com.datadoghq:dd-javac-plugin:0.2.2' } tasks.withType(JavaCompile).configureEach { @@ -91,7 +91,7 @@ Below is an example for direct compiler invocation: ```shell javac \ - -classpath dd-javac-plugin-client-0.2.1-all.jar \ + -classpath dd-javac-plugin-client-0.2.2-all.jar \ -Xplugin:DatadogCompilerPlugin \ ``` @@ -103,13 +103,16 @@ To access the injected information, use `CompilerUtils` class from the `dd-javac ```java String sourcePath = CompilerUtils.getSourcePath(MyClass.class); -int startLine = CompilerUtils.getStartLine(method); -int endLine = CompilerUtils.getEndLine(method); +int classStartLine = CompilerUtils.getStartLine(MyClass.class); +int classEndLine = CompilerUtils.getEndLine(MyClass.class); + +int methodStartLine = CompilerUtils.getStartLine(method); +int methodEndLine = CompilerUtils.getEndLine(method); ``` ## Additional configuration -Specify `disableMethodAnnotation` plugin argument if you want to disable annotating public methods. +Specify `disableSourceLinesAnnotation` plugin argument if you want to disable annotating source lines. The argument can be specified in `javac` command line after the `-Xplugin` clause. ## Limitations diff --git a/dd-javac-plugin-client/src/main/java/datadog/compiler/annotations/MethodLines.java b/dd-javac-plugin-client/src/main/java/datadog/compiler/annotations/SourceLines.java similarity index 72% rename from dd-javac-plugin-client/src/main/java/datadog/compiler/annotations/MethodLines.java rename to dd-javac-plugin-client/src/main/java/datadog/compiler/annotations/SourceLines.java index 078b2a6..6bc59e0 100644 --- a/dd-javac-plugin-client/src/main/java/datadog/compiler/annotations/MethodLines.java +++ b/dd-javac-plugin-client/src/main/java/datadog/compiler/annotations/SourceLines.java @@ -5,9 +5,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) -public @interface MethodLines { +public @interface SourceLines { int start(); int end(); } diff --git a/dd-javac-plugin-client/src/main/java/datadog/compiler/utils/CompilerUtils.java b/dd-javac-plugin-client/src/main/java/datadog/compiler/utils/CompilerUtils.java index a83ce20..fd8c0af 100644 --- a/dd-javac-plugin-client/src/main/java/datadog/compiler/utils/CompilerUtils.java +++ b/dd-javac-plugin-client/src/main/java/datadog/compiler/utils/CompilerUtils.java @@ -1,6 +1,6 @@ package datadog.compiler.utils; -import datadog.compiler.annotations.MethodLines; +import datadog.compiler.annotations.SourceLines; import datadog.compiler.annotations.SourcePath; import java.lang.reflect.Executable; @@ -41,7 +41,7 @@ public static String getSourcePath(Class clazz) { * @return Start line of the method or {@link CompilerUtils#LINE_UNKNOWN} if the line cannot be determined */ public static int getStartLine(Executable executable) { - MethodLines methodLines = executable.getAnnotation(MethodLines.class); + SourceLines methodLines = executable.getAnnotation(SourceLines.class); return methodLines != null ? methodLines.start() : LINE_UNKNOWN; } @@ -52,7 +52,29 @@ public static int getStartLine(Executable executable) { * @return End line of the method or {@link CompilerUtils#LINE_UNKNOWN} if the line cannot be determined */ public static int getEndLine(Executable executable) { - MethodLines methodLines = executable.getAnnotation(MethodLines.class); + SourceLines methodLines = executable.getAnnotation(SourceLines.class); return methodLines != null ? methodLines.end() : LINE_UNKNOWN; } + + /** + * Returns start line of the provided class (class name, modifiers and annotations are taken into account). + * + * @param clazz Class + * @return Start line of the class or {@link CompilerUtils#LINE_UNKNOWN} if the line cannot be determined + */ + public static int getStartLine(Class clazz) { + SourceLines classLines = clazz.getAnnotation(SourceLines.class); + return classLines != null ? classLines.start() : LINE_UNKNOWN; + } + + /** + * Returns end line of the provided class. + * + * @param clazz Class + * @return End line of the class or {@link CompilerUtils#LINE_UNKNOWN} if the line cannot be determined + */ + public static int getEndLine(Class clazz) { + SourceLines classLines = clazz.getAnnotation(SourceLines.class); + return classLines != null ? classLines.end() : LINE_UNKNOWN; + } } diff --git a/dd-javac-plugin-client/src/test/java/datadog/compiler/utils/CompilerUtilsTest.java b/dd-javac-plugin-client/src/test/java/datadog/compiler/utils/CompilerUtilsTest.java index 364f6bc..edaaeb3 100644 --- a/dd-javac-plugin-client/src/test/java/datadog/compiler/utils/CompilerUtilsTest.java +++ b/dd-javac-plugin-client/src/test/java/datadog/compiler/utils/CompilerUtilsTest.java @@ -1,15 +1,26 @@ package datadog.compiler.utils; +import datadog.compiler.annotations.SourceLines; import datadog.compiler.annotations.SourcePath; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.lang.reflect.Method; public class CompilerUtilsTest { private static final String TEST_CLASS_SOURCE_PATH = "/repo/src/package/TestClass.java"; + private static final int TEST_CLASS_SOURCE_LINES_START = 19; + private static final int TEST_CLASS_SOURCE_LINES_END = 24; + private static final int TEST_METHOD_SOURCE_LINES_START = 21; + private static final int TEST_METHOD_SOURCE_LINES_END = 23; @SourcePath(TEST_CLASS_SOURCE_PATH) + @SourceLines(start = TEST_CLASS_SOURCE_LINES_START, end = TEST_CLASS_SOURCE_LINES_END) private static final class TestClass { + @SourceLines(start = TEST_METHOD_SOURCE_LINES_START, end = TEST_METHOD_SOURCE_LINES_END) + public static void testMethod() { + // no op + } } @Test @@ -18,4 +29,20 @@ public void testSourcePathExtraction() { Assertions.assertEquals(TEST_CLASS_SOURCE_PATH, sourcePath); } + @Test + public void testMethodLinesExtraction() throws Exception { + Method method = TestClass.class.getDeclaredMethod("testMethod"); + int startLine = CompilerUtils.getStartLine(method); + int endLine = CompilerUtils.getEndLine(method); + Assertions.assertEquals(TEST_METHOD_SOURCE_LINES_START, startLine); + Assertions.assertEquals(TEST_METHOD_SOURCE_LINES_END, endLine); + } + + @Test + public void testClassLinesExtraction() { + int startLine = CompilerUtils.getStartLine(TestClass.class); + int endLine = CompilerUtils.getEndLine(TestClass.class); + Assertions.assertEquals(TEST_CLASS_SOURCE_LINES_START, startLine); + Assertions.assertEquals(TEST_CLASS_SOURCE_LINES_END, endLine); + } } \ No newline at end of file diff --git a/src/main/java/datadog/compiler/AnnotationsInjectingClassVisitor.java b/src/main/java/datadog/compiler/AnnotationsInjectingClassVisitor.java index 84c568a..3fec317 100644 --- a/src/main/java/datadog/compiler/AnnotationsInjectingClassVisitor.java +++ b/src/main/java/datadog/compiler/AnnotationsInjectingClassVisitor.java @@ -18,52 +18,82 @@ public class AnnotationsInjectingClassVisitor extends TreeScanner { private final TreeMaker maker; private final Names names; private final JCTree.JCAnnotation sourcePathAnnotation; - private final JCTree.JCExpression methodLinesAnnotationType; - private final boolean methodAnnotationDisabled; + private final JCTree.JCExpression sourceLinesAnnotationType; + private final boolean sourceLinesAnnotationDisabled; private final LineMap lineMap; private final EndPosTable endPositions; AnnotationsInjectingClassVisitor(TreeMaker maker, Names names, JCTree.JCAnnotation sourcePathAnnotation, - JCTree.JCExpression methodLinesAnnotationType, - boolean methodAnnotationDisabled, + JCTree.JCExpression sourceLinesAnnotationType, + boolean sourceLinesAnnotationDisabled, LineMap lineMap, EndPosTable endPositions) { this.maker = maker; this.names = names; this.sourcePathAnnotation = sourcePathAnnotation; - this.methodLinesAnnotationType = methodLinesAnnotationType; - this.methodAnnotationDisabled = methodAnnotationDisabled; + this.sourceLinesAnnotationType = sourceLinesAnnotationType; + this.sourceLinesAnnotationDisabled = sourceLinesAnnotationDisabled; this.lineMap = lineMap; this.endPositions = endPositions; } @Override public Void visitClass(ClassTree node, Void aVoid) { + boolean sourcePathDetected = false; + boolean sourceLinesDetected = false; JCTree.JCClassDecl classDeclaration = (JCTree.JCClassDecl) node; + for (JCTree.JCAnnotation annotation : classDeclaration.mods.annotations) { - if (annotation.annotationType.toString().endsWith("SourcePath")) { - // The method is already annotated with @SourcePath. + if (annotation.annotationType.toString().endsWith("SourceLines")) { + // The class is already annotated with @SourceLines. // This can happen, for instance, when code-generation tools are used // that copy annotations from interface to class - return super.visitClass(node, aVoid); + sourceLinesDetected = true; } + if (annotation.annotationType.toString().endsWith("SourcePath")) { + // The class is already annotated with @SourcePath. + sourcePathDetected = true; + } + } + + if (node.getSimpleName().length() == 0) { + // Anonymous + return super.visitClass(node, aVoid); } - if (node.getSimpleName().length() > 0) { + if (!sourcePathDetected) { classDeclaration.mods.annotations = classDeclaration.mods.annotations.prepend(sourcePathAnnotation); } + + if (!sourceLinesAnnotationDisabled && !sourceLinesDetected) { + JCTree.JCModifiers modifiers = classDeclaration.getModifiers(); + + int startPosition = modifiers.getStartPosition(); + if (startPosition == Position.NOPOS) { + startPosition = classDeclaration.getStartPosition(); + } + + int endPosition = classDeclaration.getEndPosition(endPositions); + if (endPosition == Position.NOPOS) { + return super.visitClass(node, aVoid); + } + + JCTree.JCAnnotation sourceLinesAnnotation = sourceLinesAnnotation(startPosition, endPosition); + classDeclaration.mods.annotations = classDeclaration.mods.annotations.prepend(sourceLinesAnnotation); + } + return super.visitClass(node, aVoid); } public Void visitMethod(MethodTree node, Void aVoid) { - if (!methodAnnotationDisabled && (node instanceof JCTree.JCMethodDecl)) { + if (!sourceLinesAnnotationDisabled && (node instanceof JCTree.JCMethodDecl)) { JCTree.JCMethodDecl methodDecl = (JCTree.JCMethodDecl) node; for (JCTree.JCAnnotation annotation : methodDecl.mods.annotations) { - if (annotation.annotationType.toString().endsWith("MethodLines")) { - // The method is already annotated with @MethodLines. + if (annotation.annotationType.toString().endsWith("SourceLines")) { + // The method is already annotated with @SourceLines. // This can happen, for instance, when code-generation tools are used // that copy annotations from interface methods to class methods return super.visitMethod(node, aVoid); @@ -87,26 +117,30 @@ public Void visitMethod(MethodTree node, Void aVoid) { } } - int startLine = (int) lineMap.getLineNumber(startPosition); - int endLine = (int) lineMap.getLineNumber(endPosition); - - Name startName = names.fromString("start"); - JCTree.JCIdent startIdent = maker.Ident(startName); - JCTree.JCLiteral startLiteral = maker.Literal(startLine); - JCTree.JCAssign startAssign = maker.Assign(startIdent, startLiteral); - - Name endName = names.fromString("end"); - JCTree.JCIdent endIdent = maker.Ident(endName); - JCTree.JCLiteral endLiteral = maker.Literal(endLine); - JCTree.JCAssign endAssign = maker.Assign(endIdent, endLiteral); - - JCTree.JCAnnotation methodLinesAnnotation = annotation(maker, methodLinesAnnotationType, startAssign, endAssign); - methodDecl.mods.annotations = methodDecl.mods.annotations.prepend(methodLinesAnnotation); + JCTree.JCAnnotation sourceLinesAnnotation = sourceLinesAnnotation(startPosition, endPosition); + methodDecl.mods.annotations = methodDecl.mods.annotations.prepend(sourceLinesAnnotation); } } return super.visitMethod(node, aVoid); } + private JCTree.JCAnnotation sourceLinesAnnotation(int startPosition, int endPosition) { + int startLine = (int) lineMap.getLineNumber(startPosition); + int endLine = (int) lineMap.getLineNumber(endPosition); + + Name startName = names.fromString("start"); + JCTree.JCIdent startIdent = maker.Ident(startName); + JCTree.JCLiteral startLiteral = maker.Literal(startLine); + JCTree.JCAssign startAssign = maker.Assign(startIdent, startLiteral); + + Name endName = names.fromString("end"); + JCTree.JCIdent endIdent = maker.Ident(endName); + JCTree.JCLiteral endLiteral = maker.Literal(endLine); + JCTree.JCAssign endAssign = maker.Assign(endIdent, endLiteral); + + return annotation(maker, sourceLinesAnnotationType, startAssign, endAssign); + } + private static JCTree.JCAnnotation annotation(TreeMaker maker, JCTree type, JCTree.JCExpression... arguments) { return maker.Annotation(type, List.from(arguments)); } diff --git a/src/main/java/datadog/compiler/DatadogCompilerPlugin.java b/src/main/java/datadog/compiler/DatadogCompilerPlugin.java index 6bd1259..d3d290b 100644 --- a/src/main/java/datadog/compiler/DatadogCompilerPlugin.java +++ b/src/main/java/datadog/compiler/DatadogCompilerPlugin.java @@ -10,7 +10,7 @@ public class DatadogCompilerPlugin implements Plugin { - static final String DISABLE_METHOD_ANNOTATION = "disableMethodAnnotation"; + static final String DISABLE_SOURCE_LINES_ANNOTATION = "disableSourceLinesAnnotation"; static { CompilerModuleOpener.setup(); @@ -30,8 +30,8 @@ public void init(JavacTask task, String... strings) { Context context = basicJavacTask.getContext(); Collection arguments = Arrays.asList(strings); - boolean methodAnnotationDisabled = arguments.contains(DISABLE_METHOD_ANNOTATION); - task.addTaskListener(new DatadogTaskListener(basicJavacTask, methodAnnotationDisabled)); + boolean sourceLinesAnnotationDisabled = arguments.contains(DISABLE_SOURCE_LINES_ANNOTATION); + task.addTaskListener(new DatadogTaskListener(basicJavacTask, sourceLinesAnnotationDisabled)); Log.instance(context).printRawLines(Log.WriterKind.NOTICE, NAME + " initialized"); } diff --git a/src/main/java/datadog/compiler/DatadogTaskListener.java b/src/main/java/datadog/compiler/DatadogTaskListener.java index 2fa1788..166870f 100644 --- a/src/main/java/datadog/compiler/DatadogTaskListener.java +++ b/src/main/java/datadog/compiler/DatadogTaskListener.java @@ -20,11 +20,11 @@ final class DatadogTaskListener implements TaskListener { private final BasicJavacTask basicJavacTask; - private final boolean methodAnnotationDisabled; + private final boolean sourceLinesAnnotationDisabled; - DatadogTaskListener(BasicJavacTask basicJavacTask, boolean methodAnnotationDisabled) { + DatadogTaskListener(BasicJavacTask basicJavacTask, boolean sourceLinesAnnotationDisabled) { this.basicJavacTask = basicJavacTask; - this.methodAnnotationDisabled = methodAnnotationDisabled; + this.sourceLinesAnnotationDisabled = sourceLinesAnnotationDisabled; } @Override @@ -54,7 +54,7 @@ public void finished(TaskEvent e) { JCTree.JCExpression sourcePathAnnotationType = select(maker, names, "datadog", "compiler", "annotations", "SourcePath"); JCTree.JCAnnotation sourcePathAnnotation = annotation(maker, sourcePathAnnotationType, maker.Literal(sourcePath.toString())); - JCTree.JCExpression methodLinesAnnotationType = select(maker, names, "datadog", "compiler", "annotations", "MethodLines"); + JCTree.JCExpression sourceLinesAnnotationType = select(maker, names, "datadog", "compiler", "annotations", "SourceLines"); CompilationUnitTree compilationUnit = e.getCompilationUnit(); LineMap lineMap = compilationUnit.getLineMap(); @@ -67,7 +67,7 @@ public void finished(TaskEvent e) { } AnnotationsInjectingClassVisitor treeVisitor = new AnnotationsInjectingClassVisitor( - maker, names, sourcePathAnnotation, methodLinesAnnotationType, methodAnnotationDisabled, lineMap, endPositions); + maker, names, sourcePathAnnotation, sourceLinesAnnotationType, sourceLinesAnnotationDisabled, lineMap, endPositions); compilationUnit.accept(treeVisitor, null); } catch (Throwable t) { diff --git a/src/test/java/datadog/compiler/DatadogCompilerPluginTest.java b/src/test/java/datadog/compiler/DatadogCompilerPluginTest.java index e1426c0..68e4ee7 100644 --- a/src/test/java/datadog/compiler/DatadogCompilerPluginTest.java +++ b/src/test/java/datadog/compiler/DatadogCompilerPluginTest.java @@ -63,7 +63,11 @@ public void testSourcePathInjectionPreservesAnnotations() throws Exception { try (InMemoryFileManager fileManager = compile(compiledClassName, classSource)) { Class clazz = fileManager.loadCompiledClass(compiledClassName); String sourcePath = CompilerUtils.getSourcePath(clazz); + int startLine = CompilerUtils.getStartLine(clazz); + int endLine = CompilerUtils.getEndLine(clazz); Assertions.assertEquals(InMemorySourceFile.sourcePath(compiledClassName), sourcePath, "source path was not injected"); + Assertions.assertEquals(startLine, 3, "source lines was not injected"); + Assertions.assertEquals(endLine, 5, "source lines was not injected"); Assertions.assertNotNull(clazz.getAnnotation(Deprecated.class), "existing annotation was not preserved"); } } @@ -88,7 +92,7 @@ public void testAnonymousClassCapturedFieldReference() throws Exception { } @ParameterizedTest - @MethodSource("linesInjectionArguments") + @MethodSource("methodLinesInjectionArguments") public void testMethodLinesInjection(String resourceName, String className, String methodName, @@ -111,7 +115,7 @@ public void testMethodLinesInjection(String resourceName, } } - private static Stream linesInjectionArguments() { + private static Stream methodLinesInjectionArguments() { return Stream.of( Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test", "regularMethod", new Class[0], 4, 6), Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test", "oneLineMethod", new Class[0], 8, 8), @@ -148,8 +152,45 @@ public void testConstructorLinesInjection() throws Exception { } } + @ParameterizedTest + @MethodSource("classLinesInjectionArguments") + public void testClassLinesInjection(String resourceName, + String className, + int expectedStart, + int expectedEnd) throws Exception { + String classSource; + try (InputStream classStream = ClassLoader.getSystemResourceAsStream(resourceName)) { + classSource = IOUtils.toString(classStream, Charset.defaultCharset()); + } + + String compiledClassName = resourceName.substring(0, resourceName.lastIndexOf('.')).replace('/', '.'); + try (InMemoryFileManager fileManager = compile(compiledClassName, classSource)) { + Class clazz = fileManager.loadCompiledClass(className); + int startLine = CompilerUtils.getStartLine(clazz); + int endLine = CompilerUtils.getEndLine(clazz); + Assertions.assertEquals(expectedStart, startLine); + Assertions.assertEquals(expectedEnd, endLine); + } + } + + private static Stream classLinesInjectionArguments() { + return Stream.of( + Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test", 3, 107), + Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test$1", CompilerUtils.LINE_UNKNOWN, CompilerUtils.LINE_UNKNOWN), // lines unknown for anonymous class + Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test$InnerClass", 62, 62), + Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test$SplitDefinitionClass", 69, 73), + Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test$PrivateClass", 75, 77), + Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test$DefaultClass", 79, 81), + Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test$StaticFinalClass", 83, 85), + Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test$AnnotatedClass", 87, 90), + Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test$CommentedClass", 96, 98), // we cannot establish correspondence between the class and the comment, so only actual class lines are considered here + Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test$TestInterface", 100, 102), + Arguments.of("datadog/compiler/Test.java", "datadog.compiler.Test$TestEnum", 104, 106) + ); + } + @Test - public void testMethodAnnotationDisabled() throws Exception { + public void testSourceLinesAnnotationDisabled() throws Exception { String resourceName = "datadog/compiler/Test.java"; String methodName = "regularMethod"; Class[] methodParameterTypes = new Class[0]; @@ -160,13 +201,18 @@ public void testMethodAnnotationDisabled() throws Exception { } String compiledClassName = resourceName.substring(0, resourceName.lastIndexOf('.')).replace('/', '.'); - try (InMemoryFileManager fileManager = compile(compiledClassName, classSource, DatadogCompilerPlugin.DISABLE_METHOD_ANNOTATION)) { + try (InMemoryFileManager fileManager = compile(compiledClassName, classSource, DatadogCompilerPlugin.DISABLE_SOURCE_LINES_ANNOTATION)) { Class clazz = fileManager.loadCompiledClass(compiledClassName); + int classStartLine = CompilerUtils.getStartLine(clazz); + int classEndLine = CompilerUtils.getEndLine(clazz); + Assertions.assertEquals(CompilerUtils.LINE_UNKNOWN, classStartLine); + Assertions.assertEquals(CompilerUtils.LINE_UNKNOWN, classEndLine); + Method method = clazz.getDeclaredMethod(methodName, methodParameterTypes); - int startLine = CompilerUtils.getStartLine(method); - int endLine = CompilerUtils.getEndLine(method); - Assertions.assertEquals(CompilerUtils.LINE_UNKNOWN, startLine); - Assertions.assertEquals(CompilerUtils.LINE_UNKNOWN, endLine); + int methodStartLine = CompilerUtils.getStartLine(method); + int methodEndLine = CompilerUtils.getEndLine(method); + Assertions.assertEquals(CompilerUtils.LINE_UNKNOWN, methodStartLine); + Assertions.assertEquals(CompilerUtils.LINE_UNKNOWN, methodEndLine); } } @@ -182,14 +228,21 @@ public void testInjectionSkippedIfAnnotationsAlreadyPresent() throws Exception { String compiledClassName = resourceName.substring(0, resourceName.lastIndexOf('.')).replace('/', '.'); try (InMemoryFileManager fileManager = compile(compiledClassName, classSource)) { Class clazz = fileManager.loadCompiledClass(compiledClassName); + String sourcePath = CompilerUtils.getSourcePath(clazz); Assertions.assertEquals("the-source-path", sourcePath); + int classStartLine = CompilerUtils.getStartLine(clazz); + int classEndLine = CompilerUtils.getEndLine(clazz); + Assertions.assertEquals(1, classStartLine); + Assertions.assertEquals(2, classEndLine); + Method method = clazz.getDeclaredMethod("annotatedMethod"); - int startLine = CompilerUtils.getStartLine(method); - int endLine = CompilerUtils.getEndLine(method); - Assertions.assertEquals(1, startLine); - Assertions.assertEquals(2, endLine); + + int methodStartLine = CompilerUtils.getStartLine(method); + int methodEndLine = CompilerUtils.getEndLine(method); + Assertions.assertEquals(1, methodStartLine); + Assertions.assertEquals(2, methodEndLine); } } diff --git a/src/test/resources/datadog/compiler/Test.java b/src/test/resources/datadog/compiler/Test.java index fc6459d..0fb24cc 100644 --- a/src/test/resources/datadog/compiler/Test.java +++ b/src/test/resources/datadog/compiler/Test.java @@ -65,4 +65,43 @@ public static final class InnerClass {} public Test() { // no op constructor } + + public + class + SplitDefinitionClass { + // empty class + } + + private class PrivateClass { + // empty class + } + + class DefaultClass { + // empty class + } + + public static final class StaticFinalClass { + // empty class + } + + @Deprecated + public class AnnotatedClass { + // empty class + } + + /** + * Multi line + * comment + */ + public class CommentedClass { + // empty class + } + + public interface TestInterface { + // empty interface + } + + public enum TestEnum { + // empty enum + } } diff --git a/src/test/resources/datadog/compiler/TestAnnotated.java b/src/test/resources/datadog/compiler/TestAnnotated.java index fd5ce4b..45569b2 100644 --- a/src/test/resources/datadog/compiler/TestAnnotated.java +++ b/src/test/resources/datadog/compiler/TestAnnotated.java @@ -1,12 +1,13 @@ package datadog.compiler; -import datadog.compiler.annotations.MethodLines; +import datadog.compiler.annotations.SourceLines; import datadog.compiler.annotations.SourcePath; @SourcePath("the-source-path") +@SourceLines(start = 1, end = 2) public class TestAnnotated { - @MethodLines(start = 1, end = 2) + @SourceLines(start = 1, end = 2) public void annotatedMethod() { // no op }