update
This commit is contained in:
@@ -357,6 +357,36 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
} else if (mi.getExpression() instanceof ClassInstanceCreation cic) {
|
} else if (mi.getExpression() instanceof ClassInstanceCreation cic) {
|
||||||
declaredType = click.kamil.springstatemachineexporter.ast.common.AstUtils.extractSimpleTypeName(cic.getType());
|
declaredType = click.kamil.springstatemachineexporter.ast.common.AstUtils.extractSimpleTypeName(cic.getType());
|
||||||
sourceMethod = "inline-instantiation";
|
sourceMethod = "inline-instantiation";
|
||||||
|
|
||||||
|
List<String> getterResults = constructorAnalyzer.resolveInlineInstantiationGetterResult(cic, methodName, context, new java.util.HashSet<>());
|
||||||
|
if (getterResults != null && !getterResults.isEmpty()) {
|
||||||
|
for (String gr : getterResults) {
|
||||||
|
if (gr.startsWith("ENUM_SET:")) {
|
||||||
|
for (String eVal : gr.substring(9).split(",")) {
|
||||||
|
String parsed = constantExtractor.parseEnumSetElement(eVal);
|
||||||
|
if (!polymorphicEvents.contains(parsed)) polymorphicEvents.add(parsed);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!polymorphicEvents.contains(gr)) polymorphicEvents.add(gr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TriggerPoint.builder()
|
||||||
|
.event(tp.getEvent())
|
||||||
|
.className(tp.getClassName())
|
||||||
|
.methodName(tp.getMethodName())
|
||||||
|
.sourceFile(tp.getSourceFile())
|
||||||
|
.sourceModule(tp.getSourceModule())
|
||||||
|
.stateMachineId(tp.getStateMachineId())
|
||||||
|
.sourceState(tp.getSourceState())
|
||||||
|
.lineNumber(tp.getLineNumber())
|
||||||
|
.polymorphicEvents(polymorphicEvents)
|
||||||
|
.constraint(tp.getConstraint())
|
||||||
|
.stateTypeFqn(tp.getStateTypeFqn())
|
||||||
|
.eventTypeFqn(tp.getEventTypeFqn())
|
||||||
|
.external(tp.isExternal())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
if (cic.getAnonymousClassDeclaration() != null) {
|
if (cic.getAnonymousClassDeclaration() != null) {
|
||||||
final List<String> polyEventsRef = polymorphicEvents;
|
final List<String> polyEventsRef = polymorphicEvents;
|
||||||
for (Object declObj : cic.getAnonymousClassDeclaration().bodyDeclarations()) {
|
for (Object declObj : cic.getAnonymousClassDeclaration().bodyDeclarations()) {
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ public class CallGraphPathFinder {
|
|||||||
if (neighbors != null) {
|
if (neighbors != null) {
|
||||||
for (CallEdge edge : neighbors) {
|
for (CallEdge edge : neighbors) {
|
||||||
String neighbor = edge.getTargetMethod();
|
String neighbor = edge.getTargetMethod();
|
||||||
|
if (neighbor.startsWith("java.") || neighbor.startsWith("javax.") || neighbor.startsWith("jakarta.") || neighbor.startsWith("org.springframework.")) continue;
|
||||||
if (neighbor.equals(target) || isHeuristicMatch(neighbor, target)) {
|
if (neighbor.equals(target) || isHeuristicMatch(neighbor, target)) {
|
||||||
List<String> path = new ArrayList<>(List.of(start, target));
|
List<String> path = new ArrayList<>(List.of(start, target));
|
||||||
result.add(path);
|
result.add(path);
|
||||||
|
|||||||
@@ -223,9 +223,12 @@ public class JdtCallGraphEngine extends AbstractCallGraphEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeName != null && !typeName.isEmpty()) {
|
if (typeName != null && !typeName.isEmpty()) {
|
||||||
|
org.eclipse.jdt.core.dom.TypeDeclaration resolvedTd = context.getTypeDeclaration(typeName);
|
||||||
|
if (resolvedTd != null && context.findMethodDeclaration(resolvedTd, methodName, true) != null) {
|
||||||
return typeName + "." + methodName;
|
return typeName + "." + methodName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (receiver instanceof ThisExpression) {
|
if (receiver instanceof ThisExpression) {
|
||||||
TypeDeclaration td = findEnclosingType(node);
|
TypeDeclaration td = findEnclosingType(node);
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package click.kamil.springstatemachineexporter.analysis.service;
|
||||||
|
|
||||||
|
import click.kamil.springstatemachineexporter.analysis.model.CallEdge;
|
||||||
|
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
class CallGraphPathFinderTest {
|
||||||
|
|
||||||
|
private CallGraphPathFinder pathFinder;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
pathFinder = new CallGraphPathFinder(new CodebaseContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldSkipFrameworkAndJdkPaths() {
|
||||||
|
Map<String, List<CallEdge>> graph = new HashMap<>();
|
||||||
|
|
||||||
|
// Setup an anonymized call graph where business logic delegates to a platform boundary
|
||||||
|
// e.g. BusinessService.process -> java.util.stream.Stream.map -> AnotherBusinessService.doWork
|
||||||
|
// The pathfinder should skip the java.* path, avoiding spurious hops.
|
||||||
|
|
||||||
|
graph.put("com.acme.BusinessService.process", List.of(
|
||||||
|
new CallEdge("java.util.stream.Stream.map", List.of()),
|
||||||
|
new CallEdge("com.acme.DirectService.execute", List.of())
|
||||||
|
));
|
||||||
|
graph.put("java.util.stream.Stream.map", List.of(
|
||||||
|
new CallEdge("com.acme.AnotherBusinessService.doWork", List.of())
|
||||||
|
));
|
||||||
|
graph.put("com.acme.DirectService.execute", List.of(
|
||||||
|
new CallEdge("com.acme.AnotherBusinessService.doWork", List.of())
|
||||||
|
));
|
||||||
|
|
||||||
|
List<List<String>> paths = pathFinder.findAllPaths(
|
||||||
|
"com.acme.BusinessService.process",
|
||||||
|
"com.acme.AnotherBusinessService.doWork",
|
||||||
|
graph,
|
||||||
|
new HashSet<>()
|
||||||
|
);
|
||||||
|
|
||||||
|
// It should ONLY find the direct business path, skipping the java.util path.
|
||||||
|
assertThat(paths).hasSize(1);
|
||||||
|
assertThat(paths.get(0)).containsExactly(
|
||||||
|
"com.acme.BusinessService.process",
|
||||||
|
"com.acme.DirectService.execute",
|
||||||
|
"com.acme.AnotherBusinessService.doWork"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldFollowValidBusinessPaths() {
|
||||||
|
Map<String, List<CallEdge>> graph = new HashMap<>();
|
||||||
|
|
||||||
|
graph.put("com.acme.Start.run", List.of(
|
||||||
|
new CallEdge("com.acme.Middle.process", List.of())
|
||||||
|
));
|
||||||
|
graph.put("com.acme.Middle.process", List.of(
|
||||||
|
new CallEdge("com.acme.End.finish", List.of())
|
||||||
|
));
|
||||||
|
|
||||||
|
List<List<String>> paths = pathFinder.findAllPaths(
|
||||||
|
"com.acme.Start.run",
|
||||||
|
"com.acme.End.finish",
|
||||||
|
graph,
|
||||||
|
new HashSet<>()
|
||||||
|
);
|
||||||
|
|
||||||
|
assertThat(paths).hasSize(1);
|
||||||
|
assertThat(paths.get(0)).containsExactly(
|
||||||
|
"com.acme.Start.run",
|
||||||
|
"com.acme.Middle.process",
|
||||||
|
"com.acme.End.finish"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user