Skip to content

Commit

Permalink
Add source set name to find call graph so that it is easier to invest…
Browse files Browse the repository at this point in the history
…igate relationships between main and test sources.
  • Loading branch information
sambsnyd committed Jan 23, 2025
1 parent 3ccf5a7 commit 84b7980
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 28 deletions.
18 changes: 13 additions & 5 deletions src/main/java/org/openrewrite/FindCallGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.marker.Markup;
import org.openrewrite.marker.SourceSet;
import org.openrewrite.table.CallGraph;

import java.util.*;
Expand Down Expand Up @@ -94,23 +95,28 @@ private <T extends J> T recordCall(T j, ExecutionContext ctx) {
return j;
}
Cursor scope = getCursor().dropParentUntil(it -> it instanceof J.MethodDeclaration || it instanceof J.ClassDeclaration || it instanceof SourceFile);
String sourceSet = Optional.ofNullable(scope.firstEnclosing(SourceFile.class))
.map(Tree::getMarkers)
.flatMap(m -> m.findFirst(SourceSet.class))
.map(SourceSet::getName)
.orElse("unknown");
if (scope.getValue() instanceof J.ClassDeclaration) {
boolean isInStaticInitializer = inStaticInitializer();
if ((isInStaticInitializer && scope.computeMessageIfAbsent("METHODS_CALLED_IN_STATIC_INITIALIZATION", k -> new HashSet<>()).add(method)) ||
(!isInStaticInitializer && scope.computeMessageIfAbsent("METHODS_CALLED_IN_INSTANCE_INITIALIZATION", k -> new HashSet<>()).add(method))) {
callGraph.insertRow(ctx, row(requireNonNull(((J.ClassDeclaration) scope.getValue()).getType()).getFullyQualifiedName(), method));
callGraph.insertRow(ctx, row(sourceSet, requireNonNull(((J.ClassDeclaration) scope.getValue()).getType()).getFullyQualifiedName(), method));
}
} else if (scope.getValue() instanceof J.MethodDeclaration) {
Set<JavaType.Method> methodsCalledInScope = scope.computeMessageIfAbsent("METHODS_CALLED_IN_SCOPE", k -> new HashSet<>());
if (methodsCalledInScope.add(method)) {
callGraph.insertRow(ctx, row(requireNonNull(((J.MethodDeclaration) scope.getValue()).getMethodType()), method));
callGraph.insertRow(ctx, row(sourceSet,requireNonNull(((J.MethodDeclaration) scope.getValue()).getMethodType()), method));
}
} else if (scope.getValue() instanceof SourceFile) {
// In Java there has to be a class declaration, but that isn't the case in Groovy/Kotlin/etc.
// So we'll just use the source file path instead
Set<JavaType.Method> methodsCalledInScope = scope.computeMessageIfAbsent("METHODS_CALLED_IN_SCOPE", k -> new HashSet<>());
if (methodsCalledInScope.add(method)) {
callGraph.insertRow(ctx, row(((SourceFile) scope.getValue()).getSourcePath().toString(), method));
callGraph.insertRow(ctx, row(sourceSet, ((SourceFile) scope.getValue()).getSourcePath().toString(), method));
}
}
return j;
Expand Down Expand Up @@ -139,8 +145,9 @@ private boolean inStaticInitializer() {
return inStaticInitializer.get();
}

private CallGraph.Row row(String fqn, JavaType.Method to) {
private CallGraph.Row row(String sourceSet, String fqn, JavaType.Method to) {
return new CallGraph.Row(
sourceSet,
fqn,
inStaticInitializer() ? "<clinit>" : "<init>",
"",
Expand All @@ -154,8 +161,9 @@ private CallGraph.Row row(String fqn, JavaType.Method to) {
);
}

private CallGraph.Row row(JavaType.Method from, JavaType.Method to) {
private CallGraph.Row row(String sourceSet,JavaType.Method from, JavaType.Method to) {
return new CallGraph.Row(
sourceSet,
from.getDeclaringType().getFullyQualifiedName(),
from.getName(),
parameters(from),
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/org/openrewrite/table/CallGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ public CallGraph(Recipe recipe) {

@Value
public static class Row {

@Column(displayName = "From source set",
description = "The source set from which the action is issued.")
String fromSourceSet;

@Column(displayName = "From class",
description = "The fully qualified name of the class from which the action is issued.")
String fromClass;
Expand Down
55 changes: 32 additions & 23 deletions src/test/java/org/openrewrite/FindCallGraphTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import org.openrewrite.test.TypeValidation;

import static org.assertj.core.api.Assertions.assertThat;
import static org.openrewrite.java.Assertions.java;
import static org.openrewrite.java.Assertions.*;
import static org.openrewrite.kotlin.Assertions.kotlin;

@SuppressWarnings({"UnusedAssignment", "DataFlowIssue", "InfiniteRecursion"})
Expand All @@ -39,6 +39,7 @@ void findUniqueCallsPerDeclaration() {
spec -> spec.dataTable(CallGraph.Row.class, row ->
assertThat(row).containsExactly(
new CallGraph.Row(
"main",
"Test",
"test",
"",
Expand All @@ -51,6 +52,7 @@ void findUniqueCallsPerDeclaration() {
"void"
),
new CallGraph.Row(
"main",
"Test",
"test2",
"",
Expand All @@ -64,9 +66,9 @@ void findUniqueCallsPerDeclaration() {
)
)
),
//language=java
java(
"""
mavenProject("project", srcMainJava(
//language=java
java("""
class Test {
void test() {
System.out.println("Hello");
Expand All @@ -79,7 +81,8 @@ void test2() {
}
}
"""
)
)
))
);
}

Expand All @@ -91,6 +94,7 @@ void filterStdLib() {
.dataTable(CallGraph.Row.class, row ->
assertThat(row).containsExactly(
new CallGraph.Row(
"unknown",
"Test",
"test",
"",
Expand All @@ -104,8 +108,7 @@ void filterStdLib() {
)
)),
//language=java
java(
"""
java("""
import java.util.List;
import java.util.ArrayList;
class Test {
Expand All @@ -126,6 +129,7 @@ void staticInitializer() {
spec -> spec.dataTable(CallGraph.Row.class, row ->
assertThat(row).containsExactly(
new CallGraph.Row(
"unknown",
"Scratch",
"<clinit>",
"",
Expand All @@ -138,6 +142,7 @@ void staticInitializer() {
"int"
),
new CallGraph.Row(
"unknown",
"Scratch",
"<clinit>",
"",
Expand All @@ -152,8 +157,7 @@ void staticInitializer() {
)
),
//language=java
java(
"""
java("""
class Scratch {
static int i = bar();
static {
Expand All @@ -172,6 +176,7 @@ void initializer() {
spec -> spec.dataTable(CallGraph.Row.class, row ->
assertThat(row).containsExactly(
new CallGraph.Row(
"unknown",
"Scratch",
"<init>",
"",
Expand All @@ -184,6 +189,7 @@ void initializer() {
"int"
),
new CallGraph.Row(
"unknown",
"Scratch",
"<init>",
"",
Expand All @@ -198,8 +204,7 @@ void initializer() {
)
),
//language=java
java(
"""
java("""
class Scratch {
int i = bar();
int j;
Expand All @@ -220,6 +225,7 @@ void innerClass() {
spec -> spec.dataTable(CallGraph.Row.class, row ->
assertThat(row).containsExactly(
new CallGraph.Row(
"unknown",
"A$B",
"b",
"",
Expand All @@ -232,6 +238,7 @@ void innerClass() {
"A$C"
),
new CallGraph.Row(
"unknown",
"A$B",
"b",
"",
Expand All @@ -246,8 +253,7 @@ void innerClass() {
)
),
//language=java
java(
"""
java("""
class A {
class B {
void b() {
Expand All @@ -270,6 +276,7 @@ void anonymousClass() {
spec -> spec.dataTable(CallGraph.Row.class, row ->
assertThat(row).contains(
new CallGraph.Row(
"unknown",
"B",
"call",
"",
Expand All @@ -282,6 +289,7 @@ void anonymousClass() {
"void"
),
new CallGraph.Row(
"unknown",
"B",
"<init>",
"",
Expand All @@ -294,6 +302,7 @@ void anonymousClass() {
"B$1"
),
new CallGraph.Row(
"unknown",
"B$1",
"method",
"",
Expand All @@ -308,8 +317,7 @@ void anonymousClass() {
)
),
//language=java
java(
"""
java("""
class A {
public void method() {}
}
Expand All @@ -334,6 +342,7 @@ void companionObject() {
spec -> spec.dataTable(CallGraph.Row.class, row ->
assertThat(row).containsExactly(
new CallGraph.Row(
"unknown",
"A$Companion",
"main",
"kotlin.Array<kotlin.String>",
Expand All @@ -348,8 +357,7 @@ void companionObject() {
)
),
//language=kotlin
kotlin(
"""
kotlin("""
class A {
companion object {
@JvmStatic
Expand All @@ -368,8 +376,7 @@ void missingMethodMarked() {
rewriteRun(
spec -> spec.typeValidationOptions(TypeValidation.none()),
//language=java
java(
"""
java("""
class A {
String s = foo();
}
Expand All @@ -388,6 +395,7 @@ void fieldDeclarationInitialization() {
spec -> spec.dataTable(CallGraph.Row.class, row ->
assertThat(row).containsExactly(
new CallGraph.Row(
"unknown",
"A",
"<init>",
"",
Expand All @@ -400,6 +408,7 @@ void fieldDeclarationInitialization() {
"java.lang.String"
),
new CallGraph.Row(
"unknown",
"A",
"<clinit>",
"",
Expand All @@ -414,8 +423,7 @@ void fieldDeclarationInitialization() {
)
),
//language=java
java(
"""
java("""
class A {
String instanceField = foo();
static String staticField = foo();
Expand All @@ -431,6 +439,7 @@ void initializerBlocks() {
spec -> spec.dataTable(CallGraph.Row.class, row ->
assertThat(row).containsExactly(
new CallGraph.Row(
"unknown",
"A",
"<init>",
"",
Expand All @@ -443,6 +452,7 @@ void initializerBlocks() {
"java.lang.String"
),
new CallGraph.Row(
"unknown",
"A",
"<clinit>",
"",
Expand All @@ -457,8 +467,7 @@ void initializerBlocks() {
)
),
//language=java
java(
"""
java("""
class A {
String instanceField;
{
Expand Down

0 comments on commit 84b7980

Please sign in to comment.