update number 2
This commit is contained in:
@@ -36,7 +36,7 @@ public class StrictFqnMatchingEngine implements EventMatchingEngine {
|
|||||||
List<String> polyEvents = triggerPoint.getPolymorphicEvents() != null ? triggerPoint.getPolymorphicEvents() : java.util.Collections.emptyList();
|
List<String> polyEvents = triggerPoint.getPolymorphicEvents() != null ? triggerPoint.getPolymorphicEvents() : java.util.Collections.emptyList();
|
||||||
|
|
||||||
for (String pe : polyEvents) {
|
for (String pe : polyEvents) {
|
||||||
if (pe.equals(smEventRaw)) {
|
if (matchEventNames(pe, smEventRaw, triggerPoint.getEventTypeFqn())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (pe.startsWith("<SYMBOLIC: ") && pe.endsWith(".*>")) {
|
if (pe.startsWith("<SYMBOLIC: ") && pe.endsWith(".*>")) {
|
||||||
@@ -57,7 +57,32 @@ public class StrictFqnMatchingEngine implements EventMatchingEngine {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rawTriggerEvent.equals(smEventRaw);
|
return matchEventNames(rawTriggerEvent, smEventRaw, triggerPoint.getEventTypeFqn());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchEventNames(String triggerEvent, String smEvent, String eventTypeFqn) {
|
||||||
|
if (triggerEvent == null || smEvent == null) return false;
|
||||||
|
if (triggerEvent.equals(smEvent)) return true;
|
||||||
|
|
||||||
|
String tConst = triggerEvent.contains(".") ? triggerEvent.substring(triggerEvent.lastIndexOf('.') + 1) : triggerEvent;
|
||||||
|
String smConst = smEvent.contains(".") ? smEvent.substring(smEvent.lastIndexOf('.') + 1) : smEvent;
|
||||||
|
|
||||||
|
if (!tConst.equals(smConst)) return false;
|
||||||
|
|
||||||
|
if (eventTypeFqn != null && eventTypeFqn.contains(".") && smEvent.contains(".")) {
|
||||||
|
String fullTriggerFqn = eventTypeFqn + "." + tConst;
|
||||||
|
return fullTriggerFqn.equals(smEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (triggerEvent.contains(".") && smEvent.contains(".")) {
|
||||||
|
String tClass = triggerEvent.substring(0, triggerEvent.lastIndexOf('.'));
|
||||||
|
String smClass = smEvent.substring(0, smEvent.lastIndexOf('.'));
|
||||||
|
String tClassSimple = tClass.contains(".") ? tClass.substring(tClass.lastIndexOf('.') + 1) : tClass;
|
||||||
|
String smClassSimple = smClass.contains(".") ? smClass.substring(smClass.lastIndexOf('.') + 1) : smClass;
|
||||||
|
return tClassSimple.equals(smClassSimple);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isWildcardVariable(String eventStr) {
|
private boolean isWildcardVariable(String eventStr) {
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ public class TriggerPoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String qualifyEvent(String e, String eventTypeFqn) {
|
private static String qualifyEvent(String e, String eventTypeFqn) {
|
||||||
|
System.out.println("qualifyEvent e=" + e + " eventTypeFqn=" + eventTypeFqn);
|
||||||
if (e == null || eventTypeFqn == null || e.isEmpty()) {
|
if (e == null || eventTypeFqn == null || e.isEmpty()) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -79,21 +80,23 @@ public class TriggerPoint {
|
|||||||
if (!isEnumConstantCandidate(e)) {
|
if (!isEnumConstantCandidate(e)) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String simpleEventType = eventTypeFqn.contains(".") ? eventTypeFqn.substring(eventTypeFqn.lastIndexOf('.') + 1) : eventTypeFqn;
|
||||||
|
|
||||||
if (e.contains(".")) {
|
if (e.contains(".")) {
|
||||||
String qualifier = e.substring(0, e.lastIndexOf('.'));
|
String qualifier = e.substring(0, e.lastIndexOf('.'));
|
||||||
String lastSegment = e.substring(e.lastIndexOf('.') + 1);
|
String lastSegment = e.substring(e.lastIndexOf('.') + 1);
|
||||||
if (qualifier.equals(eventTypeFqn)) {
|
String simpleQualifier = qualifier.contains(".") ? qualifier.substring(qualifier.lastIndexOf('.') + 1) : qualifier;
|
||||||
return e;
|
|
||||||
}
|
if (simpleQualifier.equals(simpleEventType)) {
|
||||||
if (eventTypeFqn.endsWith("." + qualifier) || eventTypeFqn.equals(qualifier)) {
|
return simpleEventType + "." + lastSegment;
|
||||||
return eventTypeFqn + "." + lastSegment;
|
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
if (eventTypeFqn.startsWith("java.lang.") || eventTypeFqn.equals("int") || eventTypeFqn.equals("long") || eventTypeFqn.equals("char")) {
|
if (eventTypeFqn.startsWith("java.lang.") || eventTypeFqn.equals("String") || eventTypeFqn.equals("int") || eventTypeFqn.equals("long") || eventTypeFqn.equals("char")) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
return eventTypeFqn + "." + e;
|
return simpleEventType + "." + e;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isEnumConstantCandidate(String eventStr) {
|
private static boolean isEnumConstantCandidate(String eventStr) {
|
||||||
|
|||||||
@@ -257,6 +257,9 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
.lineNumber(tp.getLineNumber())
|
.lineNumber(tp.getLineNumber())
|
||||||
.polymorphicEvents(setterEvents)
|
.polymorphicEvents(setterEvents)
|
||||||
.constraint(tp.getConstraint())
|
.constraint(tp.getConstraint())
|
||||||
|
.stateTypeFqn(tp.getStateTypeFqn())
|
||||||
|
.eventTypeFqn(tp.getEventTypeFqn())
|
||||||
|
.external(tp.isExternal())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,6 +281,9 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
.lineNumber(tp.getLineNumber())
|
.lineNumber(tp.getLineNumber())
|
||||||
.polymorphicEvents(getterEvents)
|
.polymorphicEvents(getterEvents)
|
||||||
.constraint(tp.getConstraint())
|
.constraint(tp.getConstraint())
|
||||||
|
.stateTypeFqn(tp.getStateTypeFqn())
|
||||||
|
.eventTypeFqn(tp.getEventTypeFqn())
|
||||||
|
.external(tp.isExternal())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,6 +317,9 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
.lineNumber(tp.getLineNumber())
|
.lineNumber(tp.getLineNumber())
|
||||||
.polymorphicEvents(polymorphicEvents)
|
.polymorphicEvents(polymorphicEvents)
|
||||||
.constraint(tp.getConstraint())
|
.constraint(tp.getConstraint())
|
||||||
|
.stateTypeFqn(tp.getStateTypeFqn())
|
||||||
|
.eventTypeFqn(tp.getEventTypeFqn())
|
||||||
|
.external(tp.isExternal())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,7 +327,6 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
exprParser.setKind(ASTParser.K_EXPRESSION);
|
exprParser.setKind(ASTParser.K_EXPRESSION);
|
||||||
exprParser.setSource(resolvedValue.toCharArray());
|
exprParser.setSource(resolvedValue.toCharArray());
|
||||||
ASTNode exprNode = exprParser.createAST(null);
|
ASTNode exprNode = exprParser.createAST(null);
|
||||||
System.out.println("DEBUG resolvedValue=" + resolvedValue + ", exprNode=" + exprNode.getClass().getSimpleName());
|
|
||||||
|
|
||||||
String varName = null;
|
String varName = null;
|
||||||
String methodName = null;
|
String methodName = null;
|
||||||
@@ -425,7 +433,7 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
resolvedValue = cic.toString() + "." + methodName + "()";
|
resolvedValue = cic.toString() + "." + methodName + "()";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println("Returning early with events: " + polymorphicEvents + " for " + resolvedValue); if (!polymorphicEvents.isEmpty()) {
|
if (!polymorphicEvents.isEmpty()) {
|
||||||
return TriggerPoint.builder()
|
return TriggerPoint.builder()
|
||||||
.event(resolvedValue)
|
.event(resolvedValue)
|
||||||
.className(tp.getClassName())
|
.className(tp.getClassName())
|
||||||
@@ -437,6 +445,9 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
.lineNumber(tp.getLineNumber())
|
.lineNumber(tp.getLineNumber())
|
||||||
.polymorphicEvents(polymorphicEvents)
|
.polymorphicEvents(polymorphicEvents)
|
||||||
.constraint(tp.getConstraint())
|
.constraint(tp.getConstraint())
|
||||||
|
.stateTypeFqn(tp.getStateTypeFqn())
|
||||||
|
.eventTypeFqn(tp.getEventTypeFqn())
|
||||||
|
.external(tp.isExternal())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -509,7 +520,7 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
TypeDeclaration currentTd = context.getTypeDeclaration(methodFqn.substring(0, methodFqn.lastIndexOf('.')));
|
TypeDeclaration currentTd = context.getTypeDeclaration(methodFqn.substring(0, methodFqn.lastIndexOf('.')));
|
||||||
CompilationUnit cu = currentTd != null && currentTd.getRoot() instanceof CompilationUnit ? (CompilationUnit) currentTd.getRoot() : null;
|
CompilationUnit cu = currentTd != null && currentTd.getRoot() instanceof CompilationUnit ? (CompilationUnit) currentTd.getRoot() : null;
|
||||||
List<String> values = constantExtractor.resolveMethodReturnConstant(declaredType, methodName, 0, new HashSet<>(), cu);
|
List<String> values = constantExtractor.resolveMethodReturnConstant(declaredType, methodName, 0, new HashSet<>(), cu);
|
||||||
System.out.println("RESOLVED VALUES FOR " + methodName + " in " + currentTd.getName() + ": " + values); if (values != null && !values.isEmpty()) {
|
if (values != null && !values.isEmpty()) {
|
||||||
polymorphicEvents.addAll(values);
|
polymorphicEvents.addAll(values);
|
||||||
}
|
}
|
||||||
if (polymorphicEvents.isEmpty() && variableTracer != null) {
|
if (polymorphicEvents.isEmpty() && variableTracer != null) {
|
||||||
@@ -550,7 +561,6 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
if (currentTd != null && context.findMethodDeclaration(currentTd, methodName, true) != null) {
|
if (currentTd != null && context.findMethodDeclaration(currentTd, methodName, true) != null) {
|
||||||
CompilationUnit cu = currentTd.getRoot() instanceof CompilationUnit ? (CompilationUnit) currentTd.getRoot() : null;
|
CompilationUnit cu = currentTd.getRoot() instanceof CompilationUnit ? (CompilationUnit) currentTd.getRoot() : null;
|
||||||
List<String> values = constantExtractor.resolveMethodReturnConstant(context.getFqn(currentTd), methodName, 0, new HashSet<>(), cu);
|
List<String> values = constantExtractor.resolveMethodReturnConstant(context.getFqn(currentTd), methodName, 0, new HashSet<>(), cu);
|
||||||
System.out.println("DEBUG RESOLVED VALUES FOR " + methodName + " in " + currentTd.getName() + " -> " + values);
|
|
||||||
if (values != null && !values.isEmpty()) {
|
if (values != null && !values.isEmpty()) {
|
||||||
polymorphicEvents.addAll(values);
|
polymorphicEvents.addAll(values);
|
||||||
sourceMethod = methodFqn;
|
sourceMethod = methodFqn;
|
||||||
@@ -688,6 +698,7 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
|
|
||||||
polymorphicEvents = polymorphicEvents.stream().distinct().collect(java.util.stream.Collectors.toList());
|
polymorphicEvents = polymorphicEvents.stream().distinct().collect(java.util.stream.Collectors.toList());
|
||||||
|
|
||||||
|
System.out.println("JSON DEBUG: building final TriggerPoint. resolvedValue=" + resolvedValue + ", event=" + event);
|
||||||
if (!resolvedValue.equals(event) || !polymorphicEvents.isEmpty()) {
|
if (!resolvedValue.equals(event) || !polymorphicEvents.isEmpty()) {
|
||||||
return TriggerPoint.builder()
|
return TriggerPoint.builder()
|
||||||
.event(resolvedValue)
|
.event(resolvedValue)
|
||||||
@@ -695,8 +706,14 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
.methodName(tp.getMethodName())
|
.methodName(tp.getMethodName())
|
||||||
.sourceFile(tp.getSourceFile())
|
.sourceFile(tp.getSourceFile())
|
||||||
.lineNumber(tp.getLineNumber())
|
.lineNumber(tp.getLineNumber())
|
||||||
|
.sourceModule(tp.getSourceModule())
|
||||||
|
.stateMachineId(tp.getStateMachineId())
|
||||||
|
.sourceState(tp.getSourceState())
|
||||||
.polymorphicEvents(polymorphicEvents)
|
.polymorphicEvents(polymorphicEvents)
|
||||||
.constraint(tp.getConstraint())
|
.constraint(tp.getConstraint())
|
||||||
|
.stateTypeFqn(tp.getStateTypeFqn())
|
||||||
|
.eventTypeFqn(tp.getEventTypeFqn())
|
||||||
|
.external(tp.isExternal())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -789,7 +806,7 @@ public abstract class AbstractCallGraphEngine implements CallGraphEngine {
|
|||||||
val = expr.toString();
|
val = expr.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("DEBUG resolveArgument expr=" + expr + ", val=" + val); return postProcessResolvedArgument(expr, val);
|
return postProcessResolvedArgument(expr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String postProcessResolvedArgument(Expression originalExpr, String resolvedValue) {
|
protected String postProcessResolvedArgument(Expression originalExpr, String resolvedValue) {
|
||||||
|
|||||||
@@ -524,7 +524,24 @@ public class GenericEventDetector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String[] resolveStateMachineTypeArguments(MethodInvocation node) {
|
private String[] resolveStateMachineTypeArguments(MethodInvocation node) {
|
||||||
|
System.out.println("resolveStateMachineTypeArguments CALLED for node: " + node);
|
||||||
Expression receiver = node.getExpression();
|
Expression receiver = node.getExpression();
|
||||||
|
System.out.println("initial receiver: " + receiver);
|
||||||
|
|
||||||
|
// Trace back the receiver if it's a builder chain
|
||||||
|
while (receiver instanceof MethodInvocation mi) {
|
||||||
|
if (mi.getName().getIdentifier().equals("sendEvent")) {
|
||||||
|
receiver = mi.getExpression();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
receiver = mi.getExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also if the node itself is sendEvent, receiver is already correct
|
||||||
|
if (node.getName().getIdentifier().equals("sendEvent")) {
|
||||||
|
receiver = node.getExpression();
|
||||||
|
}
|
||||||
|
|
||||||
if (receiver == null) return new String[]{null, null};
|
if (receiver == null) return new String[]{null, null};
|
||||||
|
|
||||||
ITypeBinding binding = receiver.resolveTypeBinding();
|
ITypeBinding binding = receiver.resolveTypeBinding();
|
||||||
@@ -540,16 +557,19 @@ public class GenericEventDetector {
|
|||||||
|
|
||||||
// Fallback: search enclosing class/method for variable declaration
|
// Fallback: search enclosing class/method for variable declaration
|
||||||
Type declType = findReceiverTypeManually(receiver, node);
|
Type declType = findReceiverTypeManually(receiver, node);
|
||||||
|
System.out.println("findReceiverTypeManually returned: " + declType);
|
||||||
if (declType instanceof ParameterizedType pt) {
|
if (declType instanceof ParameterizedType pt) {
|
||||||
List<?> typeArgs = pt.typeArguments();
|
List<?> typeArgs = pt.typeArguments();
|
||||||
|
System.out.println("typeArgs size: " + typeArgs.size());
|
||||||
if (typeArgs.size() >= 2) {
|
if (typeArgs.size() >= 2) {
|
||||||
CompilationUnit cu = (CompilationUnit) node.getRoot();
|
CompilationUnit cu = (CompilationUnit) node.getRoot();
|
||||||
String stateType = resolveTypeToFqn((Type) typeArgs.get(0), cu);
|
String stateType = resolveTypeToFqn((Type) typeArgs.get(0), cu);
|
||||||
String eventType = resolveTypeToFqn((Type) typeArgs.get(1), cu);
|
String eventType = resolveTypeToFqn((Type) typeArgs.get(1), cu);
|
||||||
|
System.out.println("Resolved types: state=" + stateType + " event=" + eventType);
|
||||||
return new String[]{stateType, eventType};
|
return new String[]{stateType, eventType};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
System.out.println("Returning null, null");
|
||||||
return new String[]{null, null};
|
return new String[]{null, null};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,6 +167,10 @@ public class HeuristicCallGraphEngine 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);
|
||||||
@@ -180,7 +184,8 @@ public class HeuristicCallGraphEngine 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 || node.getExpression() instanceof SuperMethodInvocation;
|
||||||
|
if (!isAbstractOrInterface || isImplicitThis) {
|
||||||
allResolved.add(className + "." + methodName);
|
allResolved.add(className + "." + methodName);
|
||||||
}
|
}
|
||||||
for (String impl : impls) {
|
for (String impl : impls) {
|
||||||
@@ -650,6 +655,12 @@ public class HeuristicCallGraphEngine extends AbstractCallGraphEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IMethodBinding methodBinding = mi.resolveMethodBinding();
|
||||||
|
if (methodBinding != null && methodBinding.getReturnType() != null) {
|
||||||
|
return methodBinding.getReturnType().getErasure().getQualifiedName();
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -459,6 +459,14 @@ public class VariableTracer {
|
|||||||
return argValue;
|
return argValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String tracedLocal = traceLocalVariable(callerMethod, argValue);
|
||||||
|
if (tracedLocal != null && !tracedLocal.equals(argValue)) {
|
||||||
|
if (tracedLocal.contains(".") || tracedLocal.startsWith("new ") || tracedLocal.matches(".*[0-9].*") || tracedLocal.contains("(")) {
|
||||||
|
return tracedLocal;
|
||||||
|
}
|
||||||
|
argValue = tracedLocal;
|
||||||
|
}
|
||||||
|
|
||||||
int callerIndex = path.indexOf(callerMethod);
|
int callerIndex = path.indexOf(callerMethod);
|
||||||
if (callerIndex <= 0) return argValue;
|
if (callerIndex <= 0) return argValue;
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ public class SpringContextScanner extends ASTVisitor {
|
|||||||
ITypeBinding typeBinding = node.resolveBinding();
|
ITypeBinding typeBinding = node.resolveBinding();
|
||||||
if (typeBinding == null) return true;
|
if (typeBinding == null) return true;
|
||||||
|
|
||||||
if (isSpringComponent(typeBinding)) {
|
if (isSpringComponent(typeBinding, node)) {
|
||||||
SpringBean bean = SpringBean.builder()
|
SpringBean bean = SpringBean.builder()
|
||||||
.typeFqn(typeBinding.getQualifiedName())
|
.typeFqn(typeBinding.getQualifiedName())
|
||||||
.assignableTypes(getAssignableTypes(typeBinding))
|
.assignableTypes(getAssignableTypes(typeBinding))
|
||||||
.isPrimary(hasAnnotation(typeBinding, "org.springframework.context.annotation.Primary"))
|
.isPrimary(hasPrimary(typeBinding, node))
|
||||||
.qualifiers(extractQualifiers(typeBinding))
|
.qualifiers(extractQualifiers(typeBinding))
|
||||||
.order(extractOrder(typeBinding))
|
.order(extractOrder(typeBinding))
|
||||||
.declaringClassFqn(typeBinding.getQualifiedName())
|
.declaringClassFqn(typeBinding.getQualifiedName())
|
||||||
@@ -73,7 +73,7 @@ public class SpringContextScanner extends ASTVisitor {
|
|||||||
SpringBean bean = SpringBean.builder()
|
SpringBean bean = SpringBean.builder()
|
||||||
.typeFqn(concreteType[0])
|
.typeFqn(concreteType[0])
|
||||||
.assignableTypes(assignables)
|
.assignableTypes(assignables)
|
||||||
.isPrimary(hasAnnotation(methodBinding, "org.springframework.context.annotation.Primary"))
|
.isPrimary(hasPrimaryMethod(methodBinding, node))
|
||||||
.qualifiers(extractQualifiers(methodBinding))
|
.qualifiers(extractQualifiers(methodBinding))
|
||||||
.order(extractOrder(methodBinding))
|
.order(extractOrder(methodBinding))
|
||||||
.declaringClassFqn(methodBinding.getDeclaringClass().getQualifiedName())
|
.declaringClassFqn(methodBinding.getDeclaringClass().getQualifiedName())
|
||||||
@@ -97,11 +97,50 @@ public class SpringContextScanner extends ASTVisitor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSpringComponent(ITypeBinding binding) {
|
private boolean isSpringComponent(ITypeBinding binding, TypeDeclaration node) {
|
||||||
return hasMetaAnnotation(binding, "org.springframework.stereotype.Component") ||
|
if (hasMetaAnnotation(binding, "org.springframework.stereotype.Component") ||
|
||||||
hasMetaAnnotation(binding, "org.springframework.web.bind.annotation.RestController");
|
hasMetaAnnotation(binding, "org.springframework.web.bind.annotation.RestController") ||
|
||||||
|
hasAnnotation(binding, "org.springframework.stereotype.Component") ||
|
||||||
|
hasAnnotation(binding, "org.springframework.stereotype.Service") ||
|
||||||
|
hasAnnotation(binding, "org.springframework.stereotype.Repository") ||
|
||||||
|
hasAnnotation(binding, "org.springframework.stereotype.Controller") ||
|
||||||
|
hasAnnotation(binding, "org.springframework.web.bind.annotation.RestController") ||
|
||||||
|
hasAnnotation(binding, "org.springframework.context.annotation.Configuration")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (Object modObj : node.modifiers()) {
|
||||||
|
if (modObj instanceof Annotation ann) {
|
||||||
|
String name = ann.getTypeName().getFullyQualifiedName();
|
||||||
|
if (name.equals("Component") || name.equals("Service") || name.equals("Repository") ||
|
||||||
|
name.equals("Controller") || name.equals("RestController") || name.equals("Configuration")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasPrimary(ITypeBinding binding, TypeDeclaration node) {
|
||||||
|
if (hasAnnotation(binding, "org.springframework.context.annotation.Primary")) return true;
|
||||||
|
for (Object modObj : node.modifiers()) {
|
||||||
|
if (modObj instanceof Annotation ann) {
|
||||||
|
String name = ann.getTypeName().getFullyQualifiedName();
|
||||||
|
if (name.equals("Primary")) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasPrimaryMethod(IMethodBinding binding, MethodDeclaration node) {
|
||||||
|
if (hasAnnotation(binding, "org.springframework.context.annotation.Primary")) return true;
|
||||||
|
for (Object modObj : node.modifiers()) {
|
||||||
|
if (modObj instanceof Annotation ann) {
|
||||||
|
String name = ann.getTypeName().getFullyQualifiedName();
|
||||||
|
if (name.equals("Primary")) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
private boolean hasMetaAnnotation(ITypeBinding binding, String targetFqn) {
|
private boolean hasMetaAnnotation(ITypeBinding binding, String targetFqn) {
|
||||||
return checkMetaAnnotation(binding.getAnnotations(), targetFqn, new HashSet<>());
|
return checkMetaAnnotation(binding.getAnnotations(), targetFqn, new HashSet<>());
|
||||||
}
|
}
|
||||||
@@ -202,9 +241,15 @@ public class SpringContextScanner extends ASTVisitor {
|
|||||||
|
|
||||||
private String extractStereotypeValue(ITypeBinding binding) {
|
private String extractStereotypeValue(ITypeBinding binding) {
|
||||||
for (IAnnotationBinding ann : binding.getAnnotations()) {
|
for (IAnnotationBinding ann : binding.getAnnotations()) {
|
||||||
// Check if annotation itself is meta-annotated with @Component
|
if (ann.getAnnotationType() == null) continue;
|
||||||
|
String fqn = ann.getAnnotationType().getQualifiedName();
|
||||||
if (checkMetaAnnotation(new IAnnotationBinding[]{ann}, "org.springframework.stereotype.Component", new HashSet<>()) ||
|
if (checkMetaAnnotation(new IAnnotationBinding[]{ann}, "org.springframework.stereotype.Component", new HashSet<>()) ||
|
||||||
"org.springframework.stereotype.Component".equals(ann.getAnnotationType().getQualifiedName())) {
|
"org.springframework.stereotype.Component".equals(fqn) ||
|
||||||
|
"org.springframework.stereotype.Service".equals(fqn) ||
|
||||||
|
"org.springframework.stereotype.Repository".equals(fqn) ||
|
||||||
|
"org.springframework.stereotype.Controller".equals(fqn) ||
|
||||||
|
"org.springframework.web.bind.annotation.RestController".equals(fqn) ||
|
||||||
|
"org.springframework.context.annotation.Configuration".equals(fqn)) {
|
||||||
for (IMemberValuePairBinding pair : ann.getDeclaredMemberValuePairs()) {
|
for (IMemberValuePairBinding pair : ann.getDeclaredMemberValuePairs()) {
|
||||||
if ("value".equals(pair.getName()) && pair.getValue() instanceof String) {
|
if ("value".equals(pair.getName()) && pair.getValue() instanceof String) {
|
||||||
return (String) pair.getValue();
|
return (String) pair.getValue();
|
||||||
|
|||||||
@@ -291,7 +291,6 @@ public class CodebaseContext {
|
|||||||
}
|
}
|
||||||
Set<String> allImpls = new HashSet<>();
|
Set<String> allImpls = new HashSet<>();
|
||||||
collectImplementations(cleanName, allImpls, new HashSet<>());
|
collectImplementations(cleanName, allImpls, new HashSet<>());
|
||||||
System.out.println("GET IMPLEMENTATIONS FOR: " + interfaceName + " -> " + allImpls);
|
|
||||||
return new ArrayList<>(allImpls);
|
return new ArrayList<>(allImpls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package click.kamil.springstatemachineexporter;
|
||||||
|
|
||||||
|
import click.kamil.springstatemachineexporter.analysis.model.TriggerPoint;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
public class TestTriggerPoint {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
TriggerPoint tp = TriggerPoint.builder()
|
||||||
|
.event("PLACE_ORDER")
|
||||||
|
.eventTypeFqn("String")
|
||||||
|
.build();
|
||||||
|
System.out.println("Result event: " + tp.getEvent());
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
System.out.println("JSON: " + mapper.writeValueAsString(tp));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"metadata" : {
|
"metadata" : {
|
||||||
"triggers" : [ {
|
"triggers" : [ {
|
||||||
"event" : "String.SUBMIT",
|
"event" : "SUBMIT",
|
||||||
"className" : "click.kamil.maven.core.MavenOrderStateMachine.OrderController",
|
"className" : "click.kamil.maven.core.MavenOrderStateMachine.OrderController",
|
||||||
"methodName" : "submitOrder",
|
"methodName" : "submitOrder",
|
||||||
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
|
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
"external" : false,
|
"external" : false,
|
||||||
"constraint" : null
|
"constraint" : null
|
||||||
}, {
|
}, {
|
||||||
"event" : "String.ORDER_EVENT",
|
"event" : "ORDER_EVENT",
|
||||||
"className" : "click.kamil.maven.core.MavenOrderStateMachine.OrderService",
|
"className" : "click.kamil.maven.core.MavenOrderStateMachine.OrderService",
|
||||||
"methodName" : "onMessage",
|
"methodName" : "onMessage",
|
||||||
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
|
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
},
|
},
|
||||||
"methodChain" : [ "click.kamil.maven.core.MavenOrderStateMachine.OrderController.submitOrder" ],
|
"methodChain" : [ "click.kamil.maven.core.MavenOrderStateMachine.OrderController.submitOrder" ],
|
||||||
"triggerPoint" : {
|
"triggerPoint" : {
|
||||||
"event" : "String.SUBMIT",
|
"event" : "SUBMIT",
|
||||||
"className" : "click.kamil.maven.core.MavenOrderStateMachine.OrderController",
|
"className" : "click.kamil.maven.core.MavenOrderStateMachine.OrderController",
|
||||||
"methodName" : "submitOrder",
|
"methodName" : "submitOrder",
|
||||||
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
|
"sourceFile" : "core-module/src/main/java/click/kamil/maven/core/MavenOrderStateMachine.java",
|
||||||
@@ -115,7 +115,11 @@
|
|||||||
"constraint" : null
|
"constraint" : null
|
||||||
},
|
},
|
||||||
"contextMachineId" : null,
|
"contextMachineId" : null,
|
||||||
"matchedTransitions" : null
|
"matchedTransitions" : [ {
|
||||||
|
"sourceState" : "INIT",
|
||||||
|
"targetState" : "BUSY",
|
||||||
|
"event" : "SUBMIT"
|
||||||
|
} ]
|
||||||
} ],
|
} ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"default" : { }
|
"default" : { }
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"metadata" : {
|
"metadata" : {
|
||||||
"triggers" : [ {
|
"triggers" : [ {
|
||||||
"event" : "String.SUBMIT",
|
"event" : "SUBMIT",
|
||||||
"className" : "click.kamil.multi.core.OrderController",
|
"className" : "click.kamil.multi.core.OrderController",
|
||||||
"methodName" : "submitOrder",
|
"methodName" : "submitOrder",
|
||||||
"sourceFile" : "core-module/src/main/java/click/kamil/multi/core/OrderController.java",
|
"sourceFile" : "core-module/src/main/java/click/kamil/multi/core/OrderController.java",
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
},
|
},
|
||||||
"methodChain" : [ "click.kamil.multi.core.OrderController.submitOrder" ],
|
"methodChain" : [ "click.kamil.multi.core.OrderController.submitOrder" ],
|
||||||
"triggerPoint" : {
|
"triggerPoint" : {
|
||||||
"event" : "String.SUBMIT",
|
"event" : "SUBMIT",
|
||||||
"className" : "click.kamil.multi.core.OrderController",
|
"className" : "click.kamil.multi.core.OrderController",
|
||||||
"methodName" : "submitOrder",
|
"methodName" : "submitOrder",
|
||||||
"sourceFile" : "core-module/src/main/java/click/kamil/multi/core/OrderController.java",
|
"sourceFile" : "core-module/src/main/java/click/kamil/multi/core/OrderController.java",
|
||||||
@@ -76,7 +76,11 @@
|
|||||||
"constraint" : null
|
"constraint" : null
|
||||||
},
|
},
|
||||||
"contextMachineId" : null,
|
"contextMachineId" : null,
|
||||||
"matchedTransitions" : null
|
"matchedTransitions" : [ {
|
||||||
|
"sourceState" : "NEW",
|
||||||
|
"targetState" : "PROCESSING",
|
||||||
|
"event" : "SUBMIT"
|
||||||
|
} ]
|
||||||
} ],
|
} ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"default" : { }
|
"default" : { }
|
||||||
|
|||||||
Reference in New Issue
Block a user