Compare commits
2 Commits
b07b7855a1
...
bcdbbffa13
| Author | SHA1 | Date | |
|---|---|---|---|
| bcdbbffa13 | |||
| 3988864494 |
@@ -69,6 +69,16 @@ public class StrictFqnMatchingEngine implements EventMatchingEngine {
|
|||||||
|
|
||||||
if (!tConst.equals(smConst)) return false;
|
if (!tConst.equals(smConst)) return false;
|
||||||
|
|
||||||
|
// Prevent matching string/primitive triggers to enum transitions
|
||||||
|
if (isStringTypeOrPrimitive(eventTypeFqn) && smEvent.contains(".")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent matching enum triggers to string transitions
|
||||||
|
if (!smEvent.contains(".") && triggerEvent.contains(".")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (eventTypeFqn != null && eventTypeFqn.contains(".") && smEvent.contains(".")) {
|
if (eventTypeFqn != null && eventTypeFqn.contains(".") && smEvent.contains(".")) {
|
||||||
String fullTriggerFqn = eventTypeFqn + "." + tConst;
|
String fullTriggerFqn = eventTypeFqn + "." + tConst;
|
||||||
return fullTriggerFqn.equals(smEvent);
|
return fullTriggerFqn.equals(smEvent);
|
||||||
@@ -85,6 +95,12 @@ public class StrictFqnMatchingEngine implements EventMatchingEngine {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isStringTypeOrPrimitive(String typeFqn) {
|
||||||
|
if (typeFqn == null) return false;
|
||||||
|
return typeFqn.equals("String") || typeFqn.equals("java.lang.String") ||
|
||||||
|
typeFqn.equals("int") || typeFqn.equals("long") || typeFqn.equals("char");
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isWildcardVariable(String eventStr) {
|
private boolean isWildcardVariable(String eventStr) {
|
||||||
if (eventStr == null) return false;
|
if (eventStr == null) return false;
|
||||||
|
|
||||||
|
|||||||
@@ -194,6 +194,30 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
if (paramIndex < edge.getArguments().size()) {
|
if (paramIndex < edge.getArguments().size()) {
|
||||||
String arg = edge.getArguments().get(paramIndex);
|
String arg = edge.getArguments().get(paramIndex);
|
||||||
if (arg != null) {
|
if (arg != null) {
|
||||||
|
if (arg.contains("(") && !arg.startsWith("new ")) {
|
||||||
|
org.eclipse.jdt.core.dom.ASTParser argParser = org.eclipse.jdt.core.dom.ASTParser.newParser(org.eclipse.jdt.core.dom.AST.JLS17);
|
||||||
|
argParser.setKind(org.eclipse.jdt.core.dom.ASTParser.K_EXPRESSION);
|
||||||
|
argParser.setSource(arg.toCharArray());
|
||||||
|
org.eclipse.jdt.core.dom.ASTNode argNode = argParser.createAST(null);
|
||||||
|
if (argNode instanceof org.eclipse.jdt.core.dom.MethodInvocation miArg && !miArg.arguments().isEmpty()) {
|
||||||
|
boolean shouldUnpack = false;
|
||||||
|
org.eclipse.jdt.core.dom.Expression recv = miArg.getExpression();
|
||||||
|
if (recv == null || recv instanceof org.eclipse.jdt.core.dom.ThisExpression) {
|
||||||
|
shouldUnpack = true;
|
||||||
|
} else if (recv instanceof org.eclipse.jdt.core.dom.SimpleName sn) {
|
||||||
|
shouldUnpack = !Character.isLowerCase(sn.getIdentifier().charAt(0));
|
||||||
|
} else if (recv instanceof org.eclipse.jdt.core.dom.QualifiedName qn) {
|
||||||
|
shouldUnpack = !Character.isLowerCase(qn.getName().getIdentifier().charAt(0));
|
||||||
|
}
|
||||||
|
if (shouldUnpack) {
|
||||||
|
org.eclipse.jdt.core.dom.Expression innerArg = (org.eclipse.jdt.core.dom.Expression) miArg.arguments().get(0);
|
||||||
|
if (miArg.getName().getIdentifier().equals("valueOf") && miArg.arguments().size() == 2) {
|
||||||
|
innerArg = (org.eclipse.jdt.core.dom.Expression) miArg.arguments().get(1);
|
||||||
|
}
|
||||||
|
arg = innerArg.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
String receiver = edge.getReceiver();
|
String receiver = edge.getReceiver();
|
||||||
String actualReceiver = null;
|
String actualReceiver = null;
|
||||||
if ("this".equals(arg) || arg.startsWith("this.") || "super".equals(arg) || arg.startsWith("super.")) {
|
if ("this".equals(arg) || arg.startsWith("this.") || "super".equals(arg) || arg.startsWith("super.")) {
|
||||||
|
|||||||
@@ -164,6 +164,10 @@ public class JdtCallGraphEngine extends AbstractCallGraphEngine {
|
|||||||
|
|
||||||
List<String> allResolved = new ArrayList<>();
|
List<String> allResolved = new ArrayList<>();
|
||||||
|
|
||||||
|
if (node.getExpression() == null) {
|
||||||
|
return Collections.singletonList(baseCalled);
|
||||||
|
}
|
||||||
|
|
||||||
if (baseCalled.contains(".")) {
|
if (baseCalled.contains(".")) {
|
||||||
String className = baseCalled.substring(0, baseCalled.lastIndexOf('.'));
|
String className = baseCalled.substring(0, baseCalled.lastIndexOf('.'));
|
||||||
String methodName = baseCalled.substring(baseCalled.lastIndexOf('.') + 1);
|
String methodName = baseCalled.substring(baseCalled.lastIndexOf('.') + 1);
|
||||||
@@ -177,7 +181,8 @@ public class JdtCallGraphEngine extends AbstractCallGraphEngine {
|
|||||||
if (td != null) {
|
if (td != null) {
|
||||||
isAbstractOrInterface = td.isInterface() || (td.modifiers() != null && td.modifiers().toString().contains("abstract"));
|
isAbstractOrInterface = td.isInterface() || (td.modifiers() != null && td.modifiers().toString().contains("abstract"));
|
||||||
}
|
}
|
||||||
if (!isAbstractOrInterface) {
|
boolean isImplicitThis = node.getExpression() == null || node.getExpression() instanceof ThisExpression;
|
||||||
|
if (!isAbstractOrInterface || isImplicitThis) {
|
||||||
allResolved.add(baseCalled);
|
allResolved.add(baseCalled);
|
||||||
}
|
}
|
||||||
for (String impl : impls) {
|
for (String impl : impls) {
|
||||||
|
|||||||
@@ -118,4 +118,26 @@ class StrictFqnMatchingEngineTest {
|
|||||||
|
|
||||||
assertThat(engine.matches(smEvent, triggerPoint)).isFalse();
|
assertThat(engine.matches(smEvent, triggerPoint)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldNotMatchStringTypeToEnumFqn() {
|
||||||
|
Event smEvent = Event.of("PAY", "com.example.OrderEvents.PAY");
|
||||||
|
TriggerPoint triggerPoint = TriggerPoint.builder()
|
||||||
|
.event("PAY")
|
||||||
|
.eventTypeFqn("java.lang.String")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertThat(engine.matches(smEvent, triggerPoint)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldNotMatchEnumTypeToStringFqn() {
|
||||||
|
Event smEvent = Event.of("PAY", "PAY");
|
||||||
|
TriggerPoint triggerPoint = TriggerPoint.builder()
|
||||||
|
.event("OrderEvents.PAY")
|
||||||
|
.eventTypeFqn("com.example.OrderEvents")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertThat(engine.matches(smEvent, triggerPoint)).isFalse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -313,6 +313,70 @@ class HeuristicCallGraphEnginePolymorphicTest {
|
|||||||
org.assertj.core.api.Assertions.assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents()).contains("POST_ACCEPTANCE_REJECTED");
|
org.assertj.core.api.Assertions.assertThat(chains.get(0).getTriggerPoint().getPolymorphicEvents()).contains("POST_ACCEPTANCE_REJECTED");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldResolvePolymorphicEventsThroughAssertSupportedMethod() throws IOException {
|
||||||
|
String source = """
|
||||||
|
package com.example;
|
||||||
|
public class Dispatcher {
|
||||||
|
private HandlerService service;
|
||||||
|
public void dispatchRequest(Payload domainEvent) {
|
||||||
|
doDispatch(domainEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doDispatch(Payload domainEvent) {
|
||||||
|
service.handleEvent(checkAndMapEvent(domainEvent.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private CustomEvents checkAndMapEvent(CustomEvents e) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HandlerService {
|
||||||
|
public void handleEvent(CustomEvents event) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Payload {
|
||||||
|
CustomEvents getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AlphaPayload implements Payload {
|
||||||
|
public CustomEvents getType() { return CustomEvents.ALPHA; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class BetaPayload implements Payload {
|
||||||
|
public CustomEvents getType() { return CustomEvents.BETA; }
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CustomEvents { ALPHA, BETA }
|
||||||
|
""";
|
||||||
|
Path tempDir = Files.createTempDirectory("callgraph_test_poly_assert");
|
||||||
|
Files.writeString(tempDir.resolve("DispatcherConfig.java"), source);
|
||||||
|
|
||||||
|
CodebaseContext context = new CodebaseContext();
|
||||||
|
context.scan(tempDir);
|
||||||
|
|
||||||
|
HeuristicCallGraphEngine builder = new HeuristicCallGraphEngine(context);
|
||||||
|
|
||||||
|
EntryPoint entryPoint = EntryPoint.builder()
|
||||||
|
.className("com.example.Dispatcher")
|
||||||
|
.methodName("dispatchRequest")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
TriggerPoint trigger = TriggerPoint.builder()
|
||||||
|
.className("com.example.HandlerService")
|
||||||
|
.methodName("handleEvent")
|
||||||
|
.event("event")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
List<CallChain> chains = builder.findChains(List.of(entryPoint), List.of(trigger));
|
||||||
|
|
||||||
|
assertThat(chains).hasSize(1);
|
||||||
|
CallChain chain = chains.get(0);
|
||||||
|
assertThat(chain.getTriggerPoint().getPolymorphicEvents())
|
||||||
|
.containsExactlyInAnyOrder("CustomEvents.ALPHA", "CustomEvents.BETA");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldResolveMappedTransitionEnumThroughAbstractBaseClassAndMultipleArgs() throws IOException {
|
void shouldResolveMappedTransitionEnumThroughAbstractBaseClassAndMultipleArgs() throws IOException {
|
||||||
String source = """
|
String source = """
|
||||||
|
|||||||
Reference in New Issue
Block a user