update
This commit is contained in:
@@ -357,6 +357,36 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
||||
} else if (mi.getExpression() instanceof ClassInstanceCreation cic) {
|
||||
declaredType = click.kamil.springstatemachineexporter.ast.common.AstUtils.extractSimpleTypeName(cic.getType());
|
||||
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) {
|
||||
final List<String> polyEventsRef = polymorphicEvents;
|
||||
for (Object declObj : cic.getAnonymousClassDeclaration().bodyDeclarations()) {
|
||||
|
||||
@@ -62,6 +62,7 @@ public class CallGraphPathFinder {
|
||||
if (neighbors != null) {
|
||||
for (CallEdge edge : neighbors) {
|
||||
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)) {
|
||||
List<String> path = new ArrayList<>(List.of(start, target));
|
||||
result.add(path);
|
||||
|
||||
@@ -223,9 +223,12 @@ public class JdtCallGraphEngine extends AbstractCallGraphEngine {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (receiver instanceof ThisExpression) {
|
||||
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