Skip to content
Closed
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
50 changes: 37 additions & 13 deletions src/main/java/com/appland/appmap/output/v1/CodeObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import javassist.CtBehavior;
import javassist.CtClass;
import javassist.bytecode.ClassFile;

import java.lang.reflect.Modifier;
import java.util.ArrayDeque;
Expand Down Expand Up @@ -194,11 +195,24 @@ 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()
};
final List<String> parts = new ArrayList(Arrays.asList("src", "main", "java"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we weren't doing this. In VSCode, if the project structure doesn't match this convention, it can actually break the "View source" link.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have a better alternative right now. The source path we can grab from the jar is partial and may match many paths. We have another branch open to explore better solutions.

Copy link
Collaborator Author

@dustinbyrne dustinbyrne Mar 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear, this heuristic is more likely to resolve to a real file than otherwise until we have a better solution in place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I think we should pull this out. It makes things worse in VSCode which is the #1 target environment.

final String packageName = classType.getPackageName();

if (packageName != null) {
parts.add(packageName.replace('.', '/'));
}

final ClassFile classFile = classType.getClassFile();
if (classFile != null) {
String sourceFile = classFile.getSourceFile();
if (sourceFile != null) {
parts.add(sourceFile);
} else {
final String className = classType.getName().replaceAll("\\$.*", "");
parts.add(className + ".java");
}
}

return String.join("/", parts);
}

Expand All @@ -209,7 +223,13 @@ public static String getSourceFilePath(CtClass classType) {
* @return The root CodeObject
*/
public static CodeObject createTree(String packageName) {
String[] packageTokens = packageName.split("\\.");
final List<String> packageTokens = new ArrayList();
if (packageName != null) {
for (String token : packageName.split("\\.")) {
packageTokens.add(token);
}
}

CodeObject rootObject = null;
CodeObject previousObject = null;

Expand Down Expand Up @@ -241,15 +261,19 @@ public static CodeObject createTree(String packageName) {
*/
public static CodeObject createTree(CtClass classType) {
String packageName = classType.getPackageName();
CodeObject classObj = new CodeObject(classType);
CodeObject rootObject = CodeObject.createTree(packageName);
CodeObject pkgLeafObject = rootObject.get(packageName);
if (pkgLeafObject == null) {
Logger.println("failed to get leaf pkg object for package " + packageName);
return null;
}
if (rootObject == null) {
rootObject = classObj;
} else {
CodeObject pkgLeafObject = rootObject.get(packageName);
if (pkgLeafObject == null) {
Logger.println("failed to get leaf pkg object for package " + packageName);
return null;
}

CodeObject classObj = new CodeObject(classType);
pkgLeafObject.addChild(classObj);
pkgLeafObject.addChild(classObj);
}

return rootObject;
}
Expand Down
68 changes: 68 additions & 0 deletions src/test/java/com/appland/appmap/output/v1/CodeObjectTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package src.test.java.com.appland.appmap.output.v1;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.appland.appmap.output.v1.CodeObject;
import com.appland.appmap.output.v1.Event;
import com.appland.appmap.test.util.ClassBuilder;

import javassist.CtClass;

import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class CodeObjectTest {

/**
* Validate the objects in a CodeObject tree match the given names and types
* @param obj The root object
* @param names The names of the objects, beginning with the root
* @param types The types of the objects, beginning with the root
*/
private void validateCodeObjectTree(CodeObject obj, String[] names, String[] types) {
CodeObject currentObject = obj;
assertTrue(currentObject != null);

for (int i = 0; currentObject != null; ++i) {
assertEquals(currentObject.name, names[i]);
assertEquals(currentObject.type, types[i]);

List<CodeObject> children = currentObject.getChildren();
if (children != null && children.size() > 0) {
currentObject = children.get(0);
} else {
currentObject = null;
}
}
}

@Test
public void testGetSourceFilePath() {
CtClass testClass = new ClassBuilder("testGetSourceFilePath1").ctClass();
assertEquals(CodeObject.getSourceFilePath(testClass), "src/main/java/testGetSourceFilePath1.java");

testClass = new ClassBuilder("com.myorg.testGetSourceFilePath2").ctClass();
assertEquals(CodeObject.getSourceFilePath(testClass), "src/main/java/com/myorg/testGetSourceFilePath2.java");
}

@Test
public void testCreateTree() {
CtClass testClass = new ClassBuilder("testCreateTree").ctClass();
validateCodeObjectTree(
CodeObject.createTree(testClass),
new String[] { "testCreateTree" },
new String[] { "class" }
);

testClass = new ClassBuilder("com.myorg.testCreateTree").ctClass();
validateCodeObjectTree(
CodeObject.createTree(testClass),
new String[] { "com", "myorg", "testCreateTree" },
new String[] { "package", "package", "class" }
);
}
}
12 changes: 11 additions & 1 deletion src/test/java/com/appland/appmap/test/util/ClassBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import org.junit.Test;
import org.junit.contrib.java.lang.system.SystemOutRule;

import javassist.CtClass;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;

public class ClassBuilderTest {
@Rule
Expand All @@ -17,4 +20,11 @@ public void testBuild() throws Exception {

assertTrue(testClass.isInstance(obj));
}
}

@Test
public void testAttributes() {
CtClass testClass = new ClassBuilder("com.example.TestAttributes").ctClass();
assertEquals(testClass.getPackageName(), "com.example");
assertEquals(testClass.getClassFile().getSourceFile(), "TestAttributes.java");
}
}