forward analysis 2
This commit is contained in:
@@ -64,6 +64,9 @@ public class ConstantResolver {
|
|||||||
String val = resolveManual(qn, context, visited);
|
String val = resolveManual(qn, context, visited);
|
||||||
return val != null ? val : qn.toString();
|
return val != null ? val : qn.toString();
|
||||||
}
|
}
|
||||||
|
if (expr instanceof FieldAccess fa) {
|
||||||
|
return resolveManual(fa.getName(), context, visited);
|
||||||
|
}
|
||||||
if (expr instanceof SimpleName sn) {
|
if (expr instanceof SimpleName sn) {
|
||||||
return resolveManual(sn, context, visited);
|
return resolveManual(sn, context, visited);
|
||||||
}
|
}
|
||||||
@@ -129,25 +132,50 @@ public class ConstantResolver {
|
|||||||
private String evaluateMethodOutput(MethodInvocation mi, MethodDeclaration md, CodebaseContext context, Set<String> visited) {
|
private String evaluateMethodOutput(MethodInvocation mi, MethodDeclaration md, CodebaseContext context, Set<String> visited) {
|
||||||
if (md.getBody() == null || mi.arguments().size() != md.parameters().size()) return null;
|
if (md.getBody() == null || mi.arguments().size() != md.parameters().size()) return null;
|
||||||
|
|
||||||
java.util.Map<String, String> paramValues = new java.util.HashMap<>();
|
java.util.Map<String, String> localVars = new java.util.HashMap<>();
|
||||||
for (int i = 0; i < mi.arguments().size(); i++) {
|
for (int i = 0; i < mi.arguments().size(); i++) {
|
||||||
Expression arg = (Expression) mi.arguments().get(i);
|
Expression arg = (Expression) mi.arguments().get(i);
|
||||||
String val = resolveInternal(arg, context, visited);
|
String val = resolveInternal(arg, context, visited);
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
org.eclipse.jdt.core.dom.SingleVariableDeclaration param = (org.eclipse.jdt.core.dom.SingleVariableDeclaration) md.parameters().get(i);
|
org.eclipse.jdt.core.dom.SingleVariableDeclaration param = (org.eclipse.jdt.core.dom.SingleVariableDeclaration) md.parameters().get(i);
|
||||||
paramValues.put(param.getName().getIdentifier(), val);
|
localVars.put(param.getName().getIdentifier(), val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paramValues.isEmpty()) return null;
|
if (localVars.isEmpty()) return null;
|
||||||
|
|
||||||
for (Object stmtObj : md.getBody().statements()) {
|
for (Object stmtObj : md.getBody().statements()) {
|
||||||
if (stmtObj instanceof org.eclipse.jdt.core.dom.SwitchStatement ss) {
|
if (stmtObj instanceof org.eclipse.jdt.core.dom.ExpressionStatement es) {
|
||||||
String result = evaluateSwitchStatement(ss, paramValues, context, visited);
|
if (es.getExpression() instanceof Assignment assignment) {
|
||||||
|
Expression lhs = assignment.getLeftHandSide();
|
||||||
|
String varName = null;
|
||||||
|
if (lhs instanceof SimpleName sn) {
|
||||||
|
varName = sn.getIdentifier();
|
||||||
|
} else if (lhs instanceof FieldAccess fa) {
|
||||||
|
varName = "this." + fa.getName().getIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
String rhsVal = resolveExpressionWithParams(assignment.getRightHandSide(), localVars);
|
||||||
|
if (rhsVal == null) rhsVal = resolveInternal(assignment.getRightHandSide(), context, visited);
|
||||||
|
|
||||||
|
if (varName != null && rhsVal != null) {
|
||||||
|
localVars.put(varName, rhsVal);
|
||||||
|
if (varName.startsWith("this.")) {
|
||||||
|
localVars.put(varName.substring(5), rhsVal); // alias without 'this.'
|
||||||
|
} else {
|
||||||
|
localVars.put("this." + varName, rhsVal); // alias with 'this.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (stmtObj instanceof org.eclipse.jdt.core.dom.SwitchStatement ss) {
|
||||||
|
String result = evaluateSwitchStatement(ss, localVars, context, visited);
|
||||||
if (result != null) return result;
|
if (result != null) return result;
|
||||||
} else if (stmtObj instanceof org.eclipse.jdt.core.dom.ReturnStatement rs) {
|
} else if (stmtObj instanceof org.eclipse.jdt.core.dom.ReturnStatement rs) {
|
||||||
if (rs.getExpression() instanceof org.eclipse.jdt.core.dom.SwitchExpression se) {
|
if (rs.getExpression() instanceof org.eclipse.jdt.core.dom.SwitchExpression se) {
|
||||||
String result = evaluateSwitchExpression(se, paramValues, context, visited);
|
String result = evaluateSwitchExpression(se, localVars, context, visited);
|
||||||
|
if (result != null) return result;
|
||||||
|
} else {
|
||||||
|
String result = resolveExpressionWithParams(rs.getExpression(), localVars);
|
||||||
if (result != null) return result;
|
if (result != null) return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,6 +252,10 @@ public class ConstantResolver {
|
|||||||
String name = sn.getIdentifier();
|
String name = sn.getIdentifier();
|
||||||
if (paramValues.containsKey(name)) return paramValues.get(name);
|
if (paramValues.containsKey(name)) return paramValues.get(name);
|
||||||
return name;
|
return name;
|
||||||
|
} else if (expr instanceof FieldAccess fa) {
|
||||||
|
String name = "this." + fa.getName().getIdentifier();
|
||||||
|
if (paramValues.containsKey(name)) return paramValues.get(name);
|
||||||
|
return null;
|
||||||
} else if (expr instanceof QualifiedName qn) {
|
} else if (expr instanceof QualifiedName qn) {
|
||||||
return qn.getName().getIdentifier();
|
return qn.getName().getIdentifier();
|
||||||
} else if (expr instanceof org.eclipse.jdt.core.dom.StringLiteral sl) {
|
} else if (expr instanceof org.eclipse.jdt.core.dom.StringLiteral sl) {
|
||||||
@@ -311,6 +343,28 @@ public class ConstantResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check constructors for assignments
|
||||||
|
for (MethodDeclaration md : td.getMethods()) {
|
||||||
|
if (md.isConstructor() && md.getBody() != null) {
|
||||||
|
for (Object stmtObj : md.getBody().statements()) {
|
||||||
|
if (stmtObj instanceof ExpressionStatement es) {
|
||||||
|
if (es.getExpression() instanceof Assignment assignment) {
|
||||||
|
Expression lhs = assignment.getLeftHandSide();
|
||||||
|
boolean matches = false;
|
||||||
|
if (lhs instanceof SimpleName snLhs && snLhs.getIdentifier().equals(fieldName)) {
|
||||||
|
matches = true;
|
||||||
|
} else if (lhs instanceof FieldAccess fa && fa.getName().getIdentifier().equals(fieldName) && fa.getExpression() instanceof ThisExpression) {
|
||||||
|
matches = true;
|
||||||
|
}
|
||||||
|
if (matches) {
|
||||||
|
return resolveInternal(assignment.getRightHandSide(), context, visited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
visited.remove(fieldId);
|
visited.remove(fieldId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,4 +152,34 @@ public class ConstantResolverTest {
|
|||||||
String result = resolver.resolve(returnExpr, context);
|
String result = resolver.resolve(returnExpr, context);
|
||||||
assertThat(result).isEqualTo("${app.path}");
|
assertThat(result).isEqualTo("${app.path}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructorAssignmentAndFieldAccess(@TempDir Path tempDir) throws IOException {
|
||||||
|
Path dir = tempDir.resolve("com/example");
|
||||||
|
Files.createDirectories(dir);
|
||||||
|
Files.writeString(dir.resolve("EventDto.java"),
|
||||||
|
"package com.example;\n" +
|
||||||
|
"public class EventDto {\n" +
|
||||||
|
" private String eventType;\n" +
|
||||||
|
" public EventDto() {\n" +
|
||||||
|
" this.eventType = \"PAYMENT_SUCCESS\";\n" +
|
||||||
|
" }\n" +
|
||||||
|
" public String getEventType() {\n" +
|
||||||
|
" return this.eventType;\n" +
|
||||||
|
" }\n" +
|
||||||
|
"}");
|
||||||
|
|
||||||
|
CodebaseContext context = new CodebaseContext();
|
||||||
|
context.scan(tempDir);
|
||||||
|
|
||||||
|
TypeDeclaration td = context.getTypeDeclaration("com.example.EventDto");
|
||||||
|
MethodDeclaration method = td.getMethods()[1]; // getEventType
|
||||||
|
ReturnStatement rs = (ReturnStatement) method.getBody().statements().get(0);
|
||||||
|
Expression returnExpr = rs.getExpression(); // this.eventType
|
||||||
|
|
||||||
|
ConstantResolver resolver = new ConstantResolver();
|
||||||
|
String result = resolver.resolve(returnExpr, context);
|
||||||
|
|
||||||
|
assertThat(result).isEqualTo("PAYMENT_SUCCESS");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user