Replace fallback string scraper with precise AST traversal
This commit is contained in:
@@ -307,8 +307,8 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// (e.g. it returned a field name like 'type', or nothing), we can scrape the resolvedValue string directly
|
|
||||||
// for string literals or enum-like constants.
|
|
||||||
boolean hasValidConstant = false;
|
boolean hasValidConstant = false;
|
||||||
for (String ev : polymorphicEvents) {
|
for (String ev : polymorphicEvents) {
|
||||||
String val = ev.contains(".") ? ev.substring(ev.lastIndexOf('.') + 1) : ev;
|
String val = ev.contains(".") ? ev.substring(ev.lastIndexOf('.') + 1) : ev;
|
||||||
@@ -318,36 +318,14 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasValidConstant && resolvedValue.contains("(")) {
|
// As a fallback, attempt direct AST extraction (e.g. from MessageBuilder chains or inline constructor args)
|
||||||
java.util.List<String> scraped = new java.util.ArrayList<>();
|
if (!hasValidConstant && exprNode instanceof org.eclipse.jdt.core.dom.Expression) {
|
||||||
|
extractConstantsFromExpression((org.eclipse.jdt.core.dom.Expression) exprNode, polymorphicEvents);
|
||||||
// Extract "STRING_LITERALS"
|
|
||||||
java.util.regex.Matcher m1 = java.util.regex.Pattern.compile("\"([^\"]+)\"").matcher(resolvedValue);
|
|
||||||
while (m1.find()) {
|
|
||||||
scraped.add(m1.group(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract ENUM_LIKE_CONSTANTS
|
|
||||||
java.util.regex.Matcher m2 = java.util.regex.Pattern.compile("\\b([A-Z_]{3,})\\b").matcher(resolvedValue);
|
|
||||||
while (m2.find()) {
|
|
||||||
if (!scraped.contains(m2.group(1))) {
|
|
||||||
scraped.add(m2.group(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!scraped.isEmpty()) {
|
|
||||||
polymorphicEvents.clear();
|
|
||||||
polymorphicEvents.addAll(scraped);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up any remaining invalid AST fallbacks (like 'type', 'event') if we found valid ones
|
// The aggressive regex scraper has been completely removed to avoid false positives.
|
||||||
if (polymorphicEvents.size() > 1) {
|
// We rely on precise AST traversal instead.
|
||||||
polymorphicEvents.removeIf(e -> {
|
|
||||||
String val = e.contains(".") ? e.substring(e.lastIndexOf('.') + 1) : e;
|
|
||||||
return !val.equals(val.toUpperCase()) || val.length() <= 2;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
List<String> newPolyEvents = new ArrayList<>();
|
List<String> newPolyEvents = new ArrayList<>();
|
||||||
for (String pe : polymorphicEvents) {
|
for (String pe : polymorphicEvents) {
|
||||||
List<String> resolved = resolveClassConstantReturns(pe, context, null);
|
List<String> resolved = resolveClassConstantReturns(pe, context, null);
|
||||||
@@ -359,6 +337,12 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
}
|
}
|
||||||
polymorphicEvents = newPolyEvents;
|
polymorphicEvents = newPolyEvents;
|
||||||
|
|
||||||
|
// Clean up any remaining invalid AST fallbacks (like 'type', 'event', or unresolved class names)
|
||||||
|
polymorphicEvents.removeIf(e -> {
|
||||||
|
String val = e.contains(".") ? e.substring(e.lastIndexOf('.') + 1) : e;
|
||||||
|
return !val.equals(val.toUpperCase()) || val.length() <= 2;
|
||||||
|
});
|
||||||
|
|
||||||
if (!resolvedValue.equals(event) || !polymorphicEvents.isEmpty()) {
|
if (!resolvedValue.equals(event) || !polymorphicEvents.isEmpty()) {
|
||||||
return TriggerPoint.builder()
|
return TriggerPoint.builder()
|
||||||
.event(resolvedValue)
|
.event(resolvedValue)
|
||||||
@@ -631,7 +615,26 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Delegate to method return analysis
|
// 2. Inline Instantiation Getter (e.g. new Event(CONSTANT).getType())
|
||||||
|
if (mi.getExpression() instanceof org.eclipse.jdt.core.dom.ClassInstanceCreation cic) {
|
||||||
|
for (Object argObj : cic.arguments()) {
|
||||||
|
extractConstantsFromExpression((org.eclipse.jdt.core.dom.Expression) argObj, constants);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Builder Pattern (e.g. MessageBuilder.withPayload(...).setHeader("event", CONSTANT).build())
|
||||||
|
org.eclipse.jdt.core.dom.Expression current = mi;
|
||||||
|
while (current instanceof org.eclipse.jdt.core.dom.MethodInvocation chainMi) {
|
||||||
|
String chainName = chainMi.getName().getIdentifier();
|
||||||
|
if (chainName.equals("setHeader") && chainMi.arguments().size() == 2) {
|
||||||
|
extractConstantsFromExpression((org.eclipse.jdt.core.dom.Expression) chainMi.arguments().get(1), constants);
|
||||||
|
} else if (chainName.equals("event") && chainMi.arguments().size() == 1) {
|
||||||
|
extractConstantsFromExpression((org.eclipse.jdt.core.dom.Expression) chainMi.arguments().get(0), constants);
|
||||||
|
}
|
||||||
|
current = chainMi.getExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Delegate to method return analysis
|
||||||
TypeDeclaration td = findEnclosingType(mi);
|
TypeDeclaration td = findEnclosingType(mi);
|
||||||
if (td != null && (mi.getExpression() == null || mi.getExpression() instanceof org.eclipse.jdt.core.dom.ThisExpression)) {
|
if (td != null && (mi.getExpression() == null || mi.getExpression() instanceof org.eclipse.jdt.core.dom.ThisExpression)) {
|
||||||
List<String> values = resolveMethodReturnConstant(context.getFqn(td), methodName, 0, new java.util.HashSet<>(), null);
|
List<String> values = resolveMethodReturnConstant(context.getFqn(td), methodName, 0, new java.util.HashSet<>(), null);
|
||||||
|
|||||||
@@ -381,10 +381,18 @@
|
|||||||
"stateMachineId" : null,
|
"stateMachineId" : null,
|
||||||
"sourceState" : null,
|
"sourceState" : null,
|
||||||
"lineNumber" : 13,
|
"lineNumber" : 13,
|
||||||
"polymorphicEvents" : [ ]
|
"polymorphicEvents" : [ "OrderEvents.PAY", "OrderEvents.CANCEL" ]
|
||||||
},
|
},
|
||||||
"contextMachineId" : null,
|
"contextMachineId" : null,
|
||||||
"matchedTransitions" : null
|
"matchedTransitions" : [ {
|
||||||
|
"sourceState" : "OrderStates.SUBMITTED",
|
||||||
|
"targetState" : "OrderStates.PAID",
|
||||||
|
"event" : "OrderEvents.PAY"
|
||||||
|
}, {
|
||||||
|
"sourceState" : "OrderStates.SUBMITTED",
|
||||||
|
"targetState" : "OrderStates.CANCELED",
|
||||||
|
"event" : "OrderEvents.CANCEL"
|
||||||
|
} ]
|
||||||
}, {
|
}, {
|
||||||
"entryPoint" : {
|
"entryPoint" : {
|
||||||
"type" : "REST",
|
"type" : "REST",
|
||||||
|
|||||||
@@ -144,7 +144,7 @@
|
|||||||
"stateMachineId" : null,
|
"stateMachineId" : null,
|
||||||
"sourceState" : null,
|
"sourceState" : null,
|
||||||
"lineNumber" : 25,
|
"lineNumber" : 25,
|
||||||
"polymorphicEvents" : [ ]
|
"polymorphicEvents" : [ "OrderEvent.PROCESS" ]
|
||||||
},
|
},
|
||||||
"contextMachineId" : null,
|
"contextMachineId" : null,
|
||||||
"matchedTransitions" : [ {
|
"matchedTransitions" : [ {
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
"stateMachineId" : null,
|
"stateMachineId" : null,
|
||||||
"sourceState" : null,
|
"sourceState" : null,
|
||||||
"lineNumber" : 25,
|
"lineNumber" : 25,
|
||||||
"polymorphicEvents" : [ ]
|
"polymorphicEvents" : [ "OrderEvent.COMPLETE" ]
|
||||||
},
|
},
|
||||||
"contextMachineId" : null,
|
"contextMachineId" : null,
|
||||||
"matchedTransitions" : [ {
|
"matchedTransitions" : [ {
|
||||||
@@ -206,7 +206,7 @@
|
|||||||
"stateMachineId" : null,
|
"stateMachineId" : null,
|
||||||
"sourceState" : null,
|
"sourceState" : null,
|
||||||
"lineNumber" : 25,
|
"lineNumber" : 25,
|
||||||
"polymorphicEvents" : [ ]
|
"polymorphicEvents" : [ "OrderEvent.CANCEL" ]
|
||||||
},
|
},
|
||||||
"contextMachineId" : null,
|
"contextMachineId" : null,
|
||||||
"matchedTransitions" : [ {
|
"matchedTransitions" : [ {
|
||||||
@@ -241,7 +241,7 @@
|
|||||||
"stateMachineId" : null,
|
"stateMachineId" : null,
|
||||||
"sourceState" : null,
|
"sourceState" : null,
|
||||||
"lineNumber" : 25,
|
"lineNumber" : 25,
|
||||||
"polymorphicEvents" : [ ]
|
"polymorphicEvents" : [ "OrderEvent.COMPLETE" ]
|
||||||
},
|
},
|
||||||
"contextMachineId" : null,
|
"contextMachineId" : null,
|
||||||
"matchedTransitions" : [ {
|
"matchedTransitions" : [ {
|
||||||
@@ -276,7 +276,7 @@
|
|||||||
"stateMachineId" : null,
|
"stateMachineId" : null,
|
||||||
"sourceState" : null,
|
"sourceState" : null,
|
||||||
"lineNumber" : 78,
|
"lineNumber" : 78,
|
||||||
"polymorphicEvents" : [ ]
|
"polymorphicEvents" : [ "OrderEvent.PROCESS" ]
|
||||||
},
|
},
|
||||||
"contextMachineId" : null,
|
"contextMachineId" : null,
|
||||||
"matchedTransitions" : [ {
|
"matchedTransitions" : [ {
|
||||||
@@ -311,7 +311,7 @@
|
|||||||
"stateMachineId" : null,
|
"stateMachineId" : null,
|
||||||
"sourceState" : null,
|
"sourceState" : null,
|
||||||
"lineNumber" : 25,
|
"lineNumber" : 25,
|
||||||
"polymorphicEvents" : [ ]
|
"polymorphicEvents" : [ "OrderEvent.PROCESS" ]
|
||||||
},
|
},
|
||||||
"contextMachineId" : null,
|
"contextMachineId" : null,
|
||||||
"matchedTransitions" : [ {
|
"matchedTransitions" : [ {
|
||||||
@@ -346,7 +346,7 @@
|
|||||||
"stateMachineId" : null,
|
"stateMachineId" : null,
|
||||||
"sourceState" : null,
|
"sourceState" : null,
|
||||||
"lineNumber" : 50,
|
"lineNumber" : 50,
|
||||||
"polymorphicEvents" : [ ]
|
"polymorphicEvents" : [ "OrderEvent.CANCEL" ]
|
||||||
},
|
},
|
||||||
"contextMachineId" : null,
|
"contextMachineId" : null,
|
||||||
"matchedTransitions" : [ {
|
"matchedTransitions" : [ {
|
||||||
|
|||||||
Reference in New Issue
Block a user