From 4734a5c096d9212664ae8d5818bc1741113e3570 Mon Sep 17 00:00:00 2001 From: Marcus Sanchez Date: Sat, 6 Mar 2021 14:43:29 -0500 Subject: [PATCH 1/2] Fix Issue 56, added better way to extract the file path. --- .../appland/appmap/output/v1/CodeObject.java | 49 +++++++++++-------- .../appmap/test/util/MethodBuilderTest.java | 4 +- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/appland/appmap/output/v1/CodeObject.java b/src/main/java/com/appland/appmap/output/v1/CodeObject.java index 6b0e1369..fcdd2332 100644 --- a/src/main/java/com/appland/appmap/output/v1/CodeObject.java +++ b/src/main/java/com/appland/appmap/output/v1/CodeObject.java @@ -1,18 +1,15 @@ package com.appland.appmap.output.v1; import com.alibaba.fastjson.annotation.JSONField; - import com.appland.appmap.util.Logger; - import javassist.CtBehavior; import javassist.CtClass; +import javassist.bytecode.SourceFileAttribute; +import java.io.File; import java.lang.reflect.Modifier; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Collections; +import java.util.*; +import java.util.regex.Matcher; /** * Represents a package, class or method. @@ -79,7 +76,7 @@ public CodeObject setLocation(String location) { public List getChildren() { return this.children; } - + /** * Return the list of children, or an empty list if there are * none. {@code getChildren} behaves differently to satisfy @@ -100,15 +97,15 @@ private CodeObject setFile(String file) { this.file = file; return this; } - + @JSONField(serialize = false, deserialize = false) private Integer lineno; private CodeObject setLineno(Integer lineno) { this.lineno = lineno; return this; } - - + + @Override public boolean equals(Object obj) { if (obj == null) { @@ -129,7 +126,7 @@ public boolean equals(Object obj) { && codeObject.isStatic == this.isStatic && (codeObject.file == null? this.file == null : codeObject.file.equals(this.file)) && codeObject.lineno == this.lineno; - + } /** @@ -194,12 +191,22 @@ public CodeObject(CodeObject src) { * @return An estimated source file path */ public static String getSourceFilePath(CtClass classType) { - String[] parts = { - "src", "main", "java", - classType.getPackageName().replace('.', '/'), - classType.getClassFile().getSourceFile() - }; - return String.join("/", parts); + + String escapedSeparator = Matcher.quoteReplacement(File.separator); + String sourceFilePath = null; + if (classType.getClassFile2().getAttribute("SourceFile") != null) { + //If debug info is available use it. + sourceFilePath = + classType.getName().substring(0, classType.getName().lastIndexOf(".")) + .replaceAll("\\.", escapedSeparator) + + ((SourceFileAttribute) classType.getClassFile2() + .getAttribute("SourceFile")).getFileName(); + } else { //If no debug info is available use new heuristics + sourceFilePath = + classType.getName().replaceAll("\\.", escapedSeparator) + .replaceAll("\\$\\w+", "") + ".java"; + } + return sourceFilePath; } /** @@ -321,7 +328,7 @@ public CodeObject get(String path) { public CodeObject findChild(String name, Boolean isStatic, int lineNumber) { for (CodeObject child : this.safeGetChildren()) { if (child.name.equals(name) - && child.isStatic == isStatic + && child.isStatic == isStatic && child.lineno == lineNumber) { return child; } @@ -357,7 +364,7 @@ private boolean equalBySubstring(String s1, String s2, int start, int end) { return true; } - + public CodeObject findChildBySubstring(String name, int start, int end) { for (CodeObject child : this.safeGetChildren()) { if (equalBySubstring(child.name, name, start, end)) { @@ -367,7 +374,7 @@ public CodeObject findChildBySubstring(String name, int start, int end) { return null; } - + /** * Add an immediate child to this CodeObject. * @param child The child to be added diff --git a/src/test/java/com/appland/appmap/test/util/MethodBuilderTest.java b/src/test/java/com/appland/appmap/test/util/MethodBuilderTest.java index b4320377..b92e29fb 100644 --- a/src/test/java/com/appland/appmap/test/util/MethodBuilderTest.java +++ b/src/test/java/com/appland/appmap/test/util/MethodBuilderTest.java @@ -32,7 +32,7 @@ public void testBuild() throws Exception { Method myMethod = testClass.getMethod("myMethod"); myMethod.invoke(obj); - assertEquals(myMethodMessage + "\n", systemOutRule.getLog()); + assertEquals(myMethodMessage + System.getProperty("line.separator"), systemOutRule.getLog()); } @Test @@ -52,7 +52,7 @@ public void testMultiParameter() throws Exception { double y = 12.0; myMethod.invoke(obj, x, y); - assertEquals(x + " " + y + "\n", systemOutRule.getLog()); + assertEquals(x + " " + y + System.getProperty("line.separator"), systemOutRule.getLog()); assertEquals(2, myMethod.getParameterCount()); assertArrayEquals(new Class[]{ int.class, double.class }, myMethod.getParameterTypes()); From 7136a4bb7e624c96e3564ab6f4006aa16a86f897 Mon Sep 17 00:00:00 2001 From: Marcus Sanchez Date: Sat, 6 Mar 2021 15:52:16 -0500 Subject: [PATCH 2/2] Fix Issue 56, added better way to extract the file path. Added tests for this. Removed src/main/java from file path calculation. --- .../appland/appmap/output/v1/CodeObject.java | 28 +++++++++-------- .../appmap/output/v1/CodeObjectTest.java | 31 +++++++++++++++++++ .../output/v1/testclasses/Anonymous.java | 13 ++++++++ .../v1/testclasses/ExampleInnerClass.java | 11 +++++++ 4 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 src/test/java/com/appland/appmap/output/v1/CodeObjectTest.java create mode 100644 src/test/java/com/appland/appmap/output/v1/testclasses/Anonymous.java create mode 100644 src/test/java/com/appland/appmap/output/v1/testclasses/ExampleInnerClass.java diff --git a/src/main/java/com/appland/appmap/output/v1/CodeObject.java b/src/main/java/com/appland/appmap/output/v1/CodeObject.java index fcdd2332..059a0af1 100644 --- a/src/main/java/com/appland/appmap/output/v1/CodeObject.java +++ b/src/main/java/com/appland/appmap/output/v1/CodeObject.java @@ -6,7 +6,6 @@ import javassist.CtClass; import javassist.bytecode.SourceFileAttribute; -import java.io.File; import java.lang.reflect.Modifier; import java.util.*; import java.util.regex.Matcher; @@ -191,24 +190,27 @@ public CodeObject(CodeObject src) { * @return An estimated source file path */ public static String getSourceFilePath(CtClass classType) { - - String escapedSeparator = Matcher.quoteReplacement(File.separator); String sourceFilePath = null; if (classType.getClassFile2().getAttribute("SourceFile") != null) { - //If debug info is available use it. - sourceFilePath = - classType.getName().substring(0, classType.getName().lastIndexOf(".")) - .replaceAll("\\.", escapedSeparator) - + ((SourceFileAttribute) classType.getClassFile2() - .getAttribute("SourceFile")).getFileName(); - } else { //If no debug info is available use new heuristics - sourceFilePath = - classType.getName().replaceAll("\\.", escapedSeparator) - .replaceAll("\\$\\w+", "") + ".java"; + sourceFilePath = getSourceFilePathWithDebugInfo(classType); + } else { + sourceFilePath = getSourceCodePath(classType); } return sourceFilePath; } + private static String getSourceFilePathWithDebugInfo(CtClass classType) { + return classType.getName().substring(0, classType.getName().lastIndexOf(".")) + .replaceAll("\\.", Matcher.quoteReplacement("/")) + + "/" + ((SourceFileAttribute) classType.getClassFile2() + .getAttribute("SourceFile")).getFileName(); + } + + private static String getSourceCodePath(CtClass classType) { + return classType.getName().replaceAll("\\.", Matcher.quoteReplacement("/")) + .replaceAll("\\$\\w+", "") + ".java"; + } + /** * Splits a package name and creates a tree of CodeObjects. For example, "com.appland.demo" would * be split into three different "package" CodeObjects: "com", "appland" and "demo". diff --git a/src/test/java/com/appland/appmap/output/v1/CodeObjectTest.java b/src/test/java/com/appland/appmap/output/v1/CodeObjectTest.java new file mode 100644 index 00000000..1c6edbdb --- /dev/null +++ b/src/test/java/com/appland/appmap/output/v1/CodeObjectTest.java @@ -0,0 +1,31 @@ +package com.appland.appmap.output.v1; + +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class CodeObjectTest { + + @Test + public void getSourceFilePath_for_RegularClass() throws NotFoundException { + CtClass testCtClass = ClassPool.getDefault().get("com.appland.appmap.ExampleClass"); + assertEquals("com/appland/appmap/ExampleClass.java", CodeObject.getSourceFilePath(testCtClass)); + } + + @Test + public void getSourceFilePath_for_InnerClass_ResultInBaseClass() throws NotFoundException { + CtClass testCtClass = ClassPool.getDefault().get("com.appland.appmap.output.v1.testclasses.ExampleInnerClass$StaticFinalInnerClass"); + assertEquals("com/appland/appmap/output/v1/testclasses/ExampleInnerClass.java", CodeObject.getSourceFilePath(testCtClass)); + } + + @Test + public void getSourceFilePath_for_AnonymousClass_ResultInBaseClass() throws NotFoundException { + CtClass testCtClass = ClassPool.getDefault().get("com.appland.appmap.output.v1.testclasses.Anonymous$1"); + assertEquals("com/appland/appmap/output/v1/testclasses/Anonymous.java", CodeObject.getSourceFilePath(testCtClass)); + } + + +} \ No newline at end of file diff --git a/src/test/java/com/appland/appmap/output/v1/testclasses/Anonymous.java b/src/test/java/com/appland/appmap/output/v1/testclasses/Anonymous.java new file mode 100644 index 00000000..d76e3793 --- /dev/null +++ b/src/test/java/com/appland/appmap/output/v1/testclasses/Anonymous.java @@ -0,0 +1,13 @@ +package com.appland.appmap.output.v1.testclasses; + +public class Anonymous { + + public static Runnable getAnonymousImpl(){ + return new Runnable() { + @Override + public void run() { + System.err.println("Hello Anonymous!"); + } + }; + } +} diff --git a/src/test/java/com/appland/appmap/output/v1/testclasses/ExampleInnerClass.java b/src/test/java/com/appland/appmap/output/v1/testclasses/ExampleInnerClass.java new file mode 100644 index 00000000..6495e09d --- /dev/null +++ b/src/test/java/com/appland/appmap/output/v1/testclasses/ExampleInnerClass.java @@ -0,0 +1,11 @@ +package com.appland.appmap.output.v1.testclasses; + +import com.appland.appmap.ExampleClass; + +public class ExampleInnerClass extends ExampleClass { + + private static final class StaticFinalInnerClass { + + } + +}