event maching heuristic update 4
This commit is contained in:
@@ -17,6 +17,19 @@ public class ConstantResolver {
|
||||
private String resolveInternal(Expression expr, CodebaseContext context, Set<String> visited) {
|
||||
if (expr == null) return null;
|
||||
|
||||
// Unwrap common wrappers
|
||||
if (expr instanceof CastExpression ce) {
|
||||
return resolveInternal(ce.getExpression(), context, visited);
|
||||
}
|
||||
if (expr instanceof ParenthesizedExpression pe) {
|
||||
return resolveInternal(pe.getExpression(), context, visited);
|
||||
}
|
||||
if (expr instanceof MethodInvocation mi && (mi.getName().getIdentifier().equals("requireNonNull") || mi.getName().getIdentifier().equals("notNull"))) {
|
||||
if (!mi.arguments().isEmpty()) {
|
||||
return resolveInternal((Expression) mi.arguments().get(0), context, visited);
|
||||
}
|
||||
}
|
||||
|
||||
// 1. Literal?
|
||||
if (expr instanceof StringLiteral sl) {
|
||||
return sl.getLiteralValue();
|
||||
|
||||
@@ -126,7 +126,10 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
org.eclipse.jdt.core.dom.Expression localSetterExpr = traceLocalSetter(entryMethod, currentParamName, localMethodName);
|
||||
if (localSetterExpr != null) {
|
||||
List<String> setterEvents = new ArrayList<>();
|
||||
extractConstantsFromExpression(localSetterExpr, setterEvents);
|
||||
List<org.eclipse.jdt.core.dom.Expression> tracedSetters = traceVariableAll(localSetterExpr);
|
||||
for (org.eclipse.jdt.core.dom.Expression tracedSetter : tracedSetters) {
|
||||
extractConstantsFromExpression(tracedSetter, setterEvents);
|
||||
}
|
||||
if (!setterEvents.isEmpty()) {
|
||||
return TriggerPoint.builder()
|
||||
.event(tp.getEvent())
|
||||
@@ -240,7 +243,10 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
org.eclipse.jdt.core.dom.Expression localSetterExpr = traceLocalSetter(entryMethod, varName, methodName);
|
||||
System.out.println("localSetterExpr = " + (localSetterExpr != null ? localSetterExpr.toString() : "null"));
|
||||
if (localSetterExpr != null) {
|
||||
extractConstantsFromExpression(localSetterExpr, polymorphicEvents);
|
||||
List<org.eclipse.jdt.core.dom.Expression> tracedSetters = traceVariableAll(localSetterExpr);
|
||||
for (org.eclipse.jdt.core.dom.Expression tracedSetter : tracedSetters) {
|
||||
extractConstantsFromExpression(tracedSetter, polymorphicEvents);
|
||||
}
|
||||
System.out.println("Extracted from setter: " + polymorphicEvents);
|
||||
if (!polymorphicEvents.isEmpty()) {
|
||||
return TriggerPoint.builder()
|
||||
@@ -496,30 +502,33 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
}
|
||||
}
|
||||
if (!handled) {
|
||||
extractConstantsFromExpression(retExpr, constants);
|
||||
String val = constantResolver.resolve(retExpr, context);
|
||||
if (val != null) {
|
||||
if (val.startsWith("ENUM_SET:")) {
|
||||
for (String eVal : val.substring(9).split(",")) {
|
||||
String parsed = parseEnumSetElement(eVal);
|
||||
if (!constants.contains(parsed)) constants.add(parsed);
|
||||
List<Expression> tracedRetExprs = traceVariableAll(retExpr);
|
||||
for (Expression tracedRetExpr : tracedRetExprs) {
|
||||
extractConstantsFromExpression(tracedRetExpr, constants);
|
||||
String val = constantResolver.resolve(tracedRetExpr, context);
|
||||
if (val != null) {
|
||||
if (val.startsWith("ENUM_SET:")) {
|
||||
for (String eVal : val.substring(9).split(",")) {
|
||||
String parsed = parseEnumSetElement(eVal);
|
||||
if (!constants.contains(parsed)) constants.add(parsed);
|
||||
}
|
||||
} else {
|
||||
if (!constants.contains(val)) constants.add(val);
|
||||
}
|
||||
} else if (tracedRetExpr instanceof org.eclipse.jdt.core.dom.SimpleName sn) {
|
||||
List<String> consts = traceFieldInConstructors(td, sn.getIdentifier(), context, visited);
|
||||
if (!consts.isEmpty()) {
|
||||
constants.addAll(consts);
|
||||
} else {
|
||||
constants.add(sn.toString());
|
||||
}
|
||||
} else if (tracedRetExpr instanceof org.eclipse.jdt.core.dom.FieldAccess fa) {
|
||||
List<String> consts = traceFieldInConstructors(td, fa.getName().getIdentifier(), context, visited);
|
||||
if (!consts.isEmpty()) {
|
||||
constants.addAll(consts);
|
||||
} else {
|
||||
constants.add(fa.getName().getIdentifier());
|
||||
}
|
||||
} else {
|
||||
if (!constants.contains(val)) constants.add(val);
|
||||
}
|
||||
} else if (retExpr instanceof org.eclipse.jdt.core.dom.SimpleName sn) {
|
||||
List<String> consts = traceFieldInConstructors(td, sn.getIdentifier(), context, visited);
|
||||
if (!consts.isEmpty()) {
|
||||
constants.addAll(consts);
|
||||
} else {
|
||||
constants.add(sn.toString());
|
||||
}
|
||||
} else if (retExpr instanceof org.eclipse.jdt.core.dom.FieldAccess fa) {
|
||||
List<String> consts = traceFieldInConstructors(td, fa.getName().getIdentifier(), context, visited);
|
||||
if (!consts.isEmpty()) {
|
||||
constants.addAll(consts);
|
||||
} else {
|
||||
constants.add(fa.getName().getIdentifier());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -542,9 +551,11 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
for (MethodDeclaration md : td.getMethods()) {
|
||||
if (md.getBody() != null) {
|
||||
md.getBody().accept(new ASTVisitor() {
|
||||
@Override
|
||||
public boolean visit(ReturnStatement node) {
|
||||
extractConstantsFromExpression(node.getExpression(), resolvedConstants);
|
||||
List<org.eclipse.jdt.core.dom.Expression> tracedReturns = traceVariableAll(node.getExpression());
|
||||
for (org.eclipse.jdt.core.dom.Expression tracedRet : tracedReturns) {
|
||||
extractConstantsFromExpression(tracedRet, resolvedConstants);
|
||||
}
|
||||
return super.visit(node);
|
||||
}
|
||||
});
|
||||
@@ -567,6 +578,8 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
extractConstantsFromExpression(pe.getExpression(), constants);
|
||||
} else if (expr instanceof org.eclipse.jdt.core.dom.CastExpression ce) {
|
||||
extractConstantsFromExpression(ce.getExpression(), constants);
|
||||
} else if (expr instanceof org.eclipse.jdt.core.dom.Assignment assignment) {
|
||||
extractConstantsFromExpression(assignment.getRightHandSide(), constants);
|
||||
} else if (expr instanceof org.eclipse.jdt.core.dom.SwitchExpression se) {
|
||||
se.accept(new org.eclipse.jdt.core.dom.ASTVisitor() {
|
||||
@Override
|
||||
@@ -1135,33 +1148,43 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
return (TypeDeclaration) parent;
|
||||
}
|
||||
private Expression traceVariable(Expression expr) {
|
||||
List<Expression> all = traceVariableAll(expr);
|
||||
return all.isEmpty() ? expr : all.get(all.size() - 1);
|
||||
}
|
||||
|
||||
private List<Expression> traceVariableAll(Expression expr) {
|
||||
List<Expression> results = new ArrayList<>();
|
||||
System.out.println("traceVariableAll called with: " + expr);
|
||||
if (expr instanceof SimpleName sn) {
|
||||
String varName = sn.getIdentifier();
|
||||
MethodDeclaration enclosingMethod = findEnclosingMethod(expr);
|
||||
System.out.println("traceVariableAll SimpleName=" + varName + " enclosingMethod=" + (enclosingMethod != null ? enclosingMethod.getName() : "null"));
|
||||
if (enclosingMethod != null) {
|
||||
final Expression[] initializer = new Expression[1];
|
||||
enclosingMethod.accept(new ASTVisitor() {
|
||||
@Override
|
||||
public boolean visit(VariableDeclarationFragment node) {
|
||||
if (node.getName().getIdentifier().equals(varName) && node.getInitializer() != null) {
|
||||
initializer[0] = node.getInitializer();
|
||||
System.out.println("traceVariableAll found init: " + node.getInitializer());
|
||||
results.addAll(traceVariableAll(node.getInitializer()));
|
||||
}
|
||||
return super.visit(node);
|
||||
}
|
||||
@Override
|
||||
public boolean visit(Assignment node) {
|
||||
if (node.getLeftHandSide() instanceof SimpleName asn && asn.getIdentifier().equals(varName)) {
|
||||
initializer[0] = node.getRightHandSide();
|
||||
System.out.println("traceVariableAll found assign: " + node.getRightHandSide());
|
||||
results.addAll(traceVariableAll(node.getRightHandSide()));
|
||||
}
|
||||
return super.visit(node);
|
||||
}
|
||||
});
|
||||
if (initializer[0] != null) {
|
||||
return traceVariable(initializer[0]);
|
||||
if (!results.isEmpty()) {
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
results.add(expr);
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<String> traceFieldInConstructors(TypeDeclaration td, String fieldName, CodebaseContext context, Set<String> visited) {
|
||||
@@ -1173,14 +1196,17 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
org.eclipse.jdt.core.dom.VariableDeclarationFragment frag = (org.eclipse.jdt.core.dom.VariableDeclarationFragment) fragObj;
|
||||
if (frag.getName().getIdentifier().equals(fieldName) && frag.getInitializer() != null) {
|
||||
Expression right = frag.getInitializer();
|
||||
if (right instanceof MethodInvocation mi) {
|
||||
String calledName = mi.getName().getIdentifier();
|
||||
String targetClass = context.getFqn(td);
|
||||
CompilationUnit cu = td.getRoot() instanceof CompilationUnit ? (CompilationUnit) td.getRoot() : null;
|
||||
results.addAll(resolveMethodReturnConstant(targetClass, calledName, 0, new HashSet<>(visited), cu));
|
||||
} else {
|
||||
String val = constantResolver.resolve(right, context);
|
||||
if (val != null) results.add(val);
|
||||
List<Expression> tracedRights = traceVariableAll(right);
|
||||
for (Expression tracedRight : tracedRights) {
|
||||
if (tracedRight instanceof MethodInvocation mi) {
|
||||
String calledName = mi.getName().getIdentifier();
|
||||
String targetClass = context.getFqn(td);
|
||||
CompilationUnit cu = td.getRoot() instanceof CompilationUnit ? (CompilationUnit) td.getRoot() : null;
|
||||
results.addAll(resolveMethodReturnConstant(targetClass, calledName, 0, new HashSet<>(visited), cu));
|
||||
} else {
|
||||
String val = constantResolver.resolve(tracedRight, context);
|
||||
if (val != null) results.add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1194,26 +1220,29 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
(left instanceof FieldAccess && ((FieldAccess) left).getName().getIdentifier().equals(fieldName))) {
|
||||
|
||||
Expression right = node.getRightHandSide();
|
||||
if (right instanceof MethodInvocation mi) {
|
||||
String calledName = mi.getName().getIdentifier();
|
||||
String targetClass = context.getFqn(td);
|
||||
|
||||
if (mi.getExpression() != null && mi.resolveMethodBinding() != null && mi.resolveMethodBinding().getDeclaringClass() != null) {
|
||||
targetClass = mi.resolveMethodBinding().getDeclaringClass().getQualifiedName();
|
||||
} else if (mi.getExpression() instanceof SimpleName) {
|
||||
String exprName = ((SimpleName) mi.getExpression()).getIdentifier();
|
||||
CompilationUnit cu = td.getRoot() instanceof CompilationUnit ? (CompilationUnit) td.getRoot() : null;
|
||||
TypeDeclaration targetTd = context.resolveStaticImport(exprName, cu);
|
||||
if (targetTd != null) {
|
||||
targetClass = context.getFqn(targetTd);
|
||||
List<Expression> tracedRights = traceVariableAll(right);
|
||||
for (Expression tracedRight : tracedRights) {
|
||||
if (tracedRight instanceof MethodInvocation mi) {
|
||||
String calledName = mi.getName().getIdentifier();
|
||||
String targetClass = context.getFqn(td);
|
||||
|
||||
if (mi.getExpression() != null && mi.resolveMethodBinding() != null && mi.resolveMethodBinding().getDeclaringClass() != null) {
|
||||
targetClass = mi.resolveMethodBinding().getDeclaringClass().getQualifiedName();
|
||||
} else if (mi.getExpression() instanceof SimpleName) {
|
||||
String exprName = ((SimpleName) mi.getExpression()).getIdentifier();
|
||||
CompilationUnit cu = td.getRoot() instanceof CompilationUnit ? (CompilationUnit) td.getRoot() : null;
|
||||
TypeDeclaration targetTd = context.resolveStaticImport(exprName, cu);
|
||||
if (targetTd != null) {
|
||||
targetClass = context.getFqn(targetTd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CompilationUnit cu = td.getRoot() instanceof CompilationUnit ? (CompilationUnit) td.getRoot() : null;
|
||||
results.addAll(resolveMethodReturnConstant(targetClass, calledName, 0, new HashSet<>(visited), cu));
|
||||
} else {
|
||||
String val = constantResolver.resolve(right, context);
|
||||
if (val != null) results.add(val);
|
||||
CompilationUnit cu = td.getRoot() instanceof CompilationUnit ? (CompilationUnit) td.getRoot() : null;
|
||||
results.addAll(resolveMethodReturnConstant(targetClass, calledName, 0, new HashSet<>(visited), cu));
|
||||
} else {
|
||||
String val = constantResolver.resolve(tracedRight, context);
|
||||
if (val != null) results.add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.visit(node);
|
||||
@@ -1303,10 +1332,11 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
public boolean visit(Assignment asn) {
|
||||
Expression left = asn.getLeftHandSide();
|
||||
if ((left instanceof SimpleName sn && sn.getIdentifier().equals(fieldName)) ||
|
||||
(left instanceof FieldAccess fa && fa.getName().getIdentifier().equals(fieldName))) {
|
||||
(left instanceof FieldAccess fa && fa.getName().getIdentifier().equals(fieldName)) ||
|
||||
(left instanceof SuperFieldAccess sfa && sfa.getName().getIdentifier().equals(fieldName))) {
|
||||
Expression right = asn.getRightHandSide();
|
||||
if (right instanceof SimpleName snRight) {
|
||||
String rightName = snRight.getIdentifier();
|
||||
String rightName = extractVariableName(right);
|
||||
if (rightName != null) {
|
||||
for (int i = 0; i < constructorMd.parameters().size(); i++) {
|
||||
SingleVariableDeclaration svd = (SingleVariableDeclaration) constructorMd.parameters().get(i);
|
||||
if (svd.getName().getIdentifier().equals(rightName)) {
|
||||
@@ -1319,15 +1349,22 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
}
|
||||
@Override
|
||||
public boolean visit(ConstructorInvocation node) {
|
||||
org.eclipse.jdt.core.dom.IMethodBinding resolvedBinding = node.resolveConstructorBinding();
|
||||
TypeDeclaration enclosingTd = findEnclosingType(node);
|
||||
if (enclosingTd != null) {
|
||||
for (MethodDeclaration otherMd : enclosingTd.getMethods()) {
|
||||
if (otherMd.isConstructor() && otherMd != constructorMd && otherMd.parameters().size() == node.arguments().size()) {
|
||||
boolean matches = false;
|
||||
if (resolvedBinding != null && otherMd.resolveBinding() != null) {
|
||||
matches = resolvedBinding.isEqualTo(otherMd.resolveBinding()) || resolvedBinding.getKey().equals(otherMd.resolveBinding().getKey());
|
||||
} else {
|
||||
matches = otherMd.isConstructor() && otherMd != constructorMd && otherMd.parameters().size() == node.arguments().size();
|
||||
}
|
||||
if (matches) {
|
||||
int targetIdx = findAssignedParameterIndex(otherMd, fieldName, context, visited);
|
||||
if (targetIdx >= 0 && targetIdx < node.arguments().size()) {
|
||||
Expression arg = (Expression) node.arguments().get(targetIdx);
|
||||
if (arg instanceof SimpleName snArg) {
|
||||
String argName = snArg.getIdentifier();
|
||||
String argName = extractVariableName(arg);
|
||||
if (argName != null) {
|
||||
for (int i = 0; i < constructorMd.parameters().size(); i++) {
|
||||
SingleVariableDeclaration svd = (SingleVariableDeclaration) constructorMd.parameters().get(i);
|
||||
if (svd.getName().getIdentifier().equals(argName)) {
|
||||
@@ -1343,6 +1380,7 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
}
|
||||
@Override
|
||||
public boolean visit(SuperConstructorInvocation node) {
|
||||
org.eclipse.jdt.core.dom.IMethodBinding resolvedBinding = node.resolveConstructorBinding();
|
||||
TypeDeclaration enclosingTd = findEnclosingType(node);
|
||||
if (enclosingTd != null) {
|
||||
String superFqn = context.getSuperclassFqn(enclosingTd);
|
||||
@@ -1350,12 +1388,18 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
TypeDeclaration superTd = context.getTypeDeclaration(superFqn);
|
||||
if (superTd != null) {
|
||||
for (MethodDeclaration otherMd : superTd.getMethods()) {
|
||||
if (otherMd.isConstructor() && otherMd.parameters().size() == node.arguments().size()) {
|
||||
boolean matches = false;
|
||||
if (resolvedBinding != null && otherMd.resolveBinding() != null) {
|
||||
matches = resolvedBinding.isEqualTo(otherMd.resolveBinding()) || resolvedBinding.getKey().equals(otherMd.resolveBinding().getKey());
|
||||
} else {
|
||||
matches = otherMd.isConstructor() && otherMd.parameters().size() == node.arguments().size();
|
||||
}
|
||||
if (matches) {
|
||||
int targetIdx = findAssignedParameterIndex(otherMd, fieldName, context, visited);
|
||||
if (targetIdx >= 0 && targetIdx < node.arguments().size()) {
|
||||
Expression arg = (Expression) node.arguments().get(targetIdx);
|
||||
if (arg instanceof SimpleName snArg) {
|
||||
String argName = snArg.getIdentifier();
|
||||
String argName = extractVariableName(arg);
|
||||
if (argName != null) {
|
||||
for (int i = 0; i < constructorMd.parameters().size(); i++) {
|
||||
SingleVariableDeclaration svd = (SingleVariableDeclaration) constructorMd.parameters().get(i);
|
||||
if (svd.getName().getIdentifier().equals(argName)) {
|
||||
@@ -1374,4 +1418,16 @@ public class HeuristicCallGraphEngine implements CallGraphEngine {
|
||||
});
|
||||
return foundIdx[0];
|
||||
}
|
||||
|
||||
private String extractVariableName(Expression expr) {
|
||||
if (expr instanceof SimpleName sn) return sn.getIdentifier();
|
||||
if (expr instanceof FieldAccess fa) return fa.getName().getIdentifier();
|
||||
if (expr instanceof SuperFieldAccess sfa) return sfa.getName().getIdentifier();
|
||||
if (expr instanceof CastExpression ce) return extractVariableName(ce.getExpression());
|
||||
if (expr instanceof ParenthesizedExpression pe) return extractVariableName(pe.getExpression());
|
||||
if (expr instanceof MethodInvocation mi && (mi.getName().getIdentifier().equals("requireNonNull") || mi.getName().getIdentifier().equals("notNull"))) {
|
||||
if (!mi.arguments().isEmpty()) return extractVariableName((Expression)mi.arguments().get(0));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user