gemini back 2
This commit is contained in:
@@ -120,6 +120,30 @@ import java.util.*;
|
||||
if (paramIndex < edge.getArguments().size()) {
|
||||
String arg = edge.getArguments().get(paramIndex);
|
||||
if (arg != null) {
|
||||
String receiver = edge.getReceiver();
|
||||
String actualReceiver = null;
|
||||
if ("this".equals(arg) || arg.startsWith("this.") || "super".equals(arg) || arg.startsWith("super.")) {
|
||||
if (i - 1 > 0) {
|
||||
String prevCaller = path.get(i - 2);
|
||||
List<CallEdge> prevEdges = callGraph.get(prevCaller);
|
||||
if (prevEdges != null) {
|
||||
for (CallEdge prevEdge : prevEdges) {
|
||||
if (prevEdge.getTargetMethod().equals(caller) || isHeuristicMatch(prevEdge.getTargetMethod(), caller)) {
|
||||
actualReceiver = prevEdge.getReceiver();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (actualReceiver == null) {
|
||||
actualReceiver = "this";
|
||||
}
|
||||
if ("this".equals(arg) || arg.startsWith("this.")) {
|
||||
arg = arg.replaceFirst("^this", actualReceiver);
|
||||
} else if ("super".equals(arg) || arg.startsWith("super.")) {
|
||||
arg = arg.replaceFirst("^super", actualReceiver);
|
||||
}
|
||||
}
|
||||
// If the argument passed has a method call, extract it
|
||||
String[] extractedArg = extractMethodSuffix(arg, methodSuffix);
|
||||
arg = extractedArg[0];
|
||||
@@ -166,6 +190,25 @@ import java.util.*;
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasGetterOnReceiver = methodSuffix.startsWith(".get") && currentParamName != null
|
||||
&& !currentParamName.contains(".") && !currentParamName.contains("(") && !currentParamName.contains("new ");
|
||||
if (hasGetterOnReceiver) {
|
||||
List<String> getterEvents = evaluateGetterOnReceiver(resolvedValue, methodSuffix, entryMethod, path, callGraph);
|
||||
if (getterEvents != null && !getterEvents.isEmpty()) {
|
||||
return TriggerPoint.builder()
|
||||
.event(tp.getEvent())
|
||||
.className(tp.getClassName())
|
||||
.methodName(tp.getMethodName())
|
||||
.sourceFile(tp.getSourceFile())
|
||||
.sourceModule(tp.getSourceModule())
|
||||
.stateMachineId(tp.getStateMachineId())
|
||||
.sourceState(tp.getSourceState())
|
||||
.lineNumber(tp.getLineNumber())
|
||||
.polymorphicEvents(getterEvents)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
String tracedVar = traceLocalVariable(entryMethod, currentParamName);
|
||||
if (tracedVar != null && !tracedVar.equals(currentParamName)) {
|
||||
String[] extractedFinalTraced = extractMethodSuffix(tracedVar, methodSuffix);
|
||||
@@ -2413,4 +2456,125 @@ import java.util.*;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected List<String> evaluateGetterOnReceiver(String resolvedValue, String methodSuffix, String entryMethod, List<String> path, Map<String, List<CallEdge>> callGraph) {
|
||||
org.eclipse.jdt.core.dom.ASTParser exprParser = org.eclipse.jdt.core.dom.ASTParser.newParser(org.eclipse.jdt.core.dom.AST.JLS17);
|
||||
exprParser.setKind(org.eclipse.jdt.core.dom.ASTParser.K_EXPRESSION);
|
||||
exprParser.setSource(resolvedValue.toCharArray());
|
||||
org.eclipse.jdt.core.dom.ASTNode exprNode = exprParser.createAST(null);
|
||||
|
||||
if (exprNode instanceof org.eclipse.jdt.core.dom.MethodInvocation mi) {
|
||||
String getterName = mi.getName().getIdentifier();
|
||||
org.eclipse.jdt.core.dom.Expression receiver = mi.getExpression();
|
||||
String receiverName = null;
|
||||
String receiverType = null;
|
||||
|
||||
if (receiver instanceof org.eclipse.jdt.core.dom.SimpleName sn) {
|
||||
receiverName = sn.getIdentifier();
|
||||
receiverType = getVariableDeclaredType(entryMethod, receiverName);
|
||||
}
|
||||
|
||||
if (receiverType == null && path.size() > 1) {
|
||||
String callerMethod = path.get(1);
|
||||
receiverType = getVariableDeclaredType(callerMethod, receiverName);
|
||||
}
|
||||
|
||||
if (receiverType != null) {
|
||||
String simpleReceiverType = receiverType;
|
||||
if (receiverType.contains("<")) {
|
||||
String rawType = receiverType.substring(0, receiverType.indexOf('<'));
|
||||
if (rawType.equals("List") || rawType.equals("Set") || rawType.equals("Collection") || rawType.equals("Iterable") || context.getTypeDeclaration(rawType) == null) {
|
||||
int start = receiverType.indexOf('<');
|
||||
int end = receiverType.lastIndexOf('>');
|
||||
if (start >= 0 && end > start) {
|
||||
simpleReceiverType = receiverType.substring(start + 1, end);
|
||||
}
|
||||
} else {
|
||||
simpleReceiverType = rawType;
|
||||
}
|
||||
}
|
||||
TypeDeclaration td = context.getTypeDeclaration(simpleReceiverType);
|
||||
if (td != null) {
|
||||
Map<String, String> fieldValues = new HashMap<>();
|
||||
String varName = receiverName;
|
||||
org.eclipse.jdt.core.dom.Expression initExpr = findVariableInitializer(entryMethod, varName);
|
||||
if (initExpr instanceof org.eclipse.jdt.core.dom.MethodInvocation initMi) {
|
||||
initExpr = unwrapMethodInvocation(initMi, 0);
|
||||
}
|
||||
if (!(initExpr instanceof org.eclipse.jdt.core.dom.ClassInstanceCreation cic)) {
|
||||
return null;
|
||||
}
|
||||
MethodDeclaration getter = null;
|
||||
if (cic.getAnonymousClassDeclaration() != null) {
|
||||
for (Object declObj : cic.getAnonymousClassDeclaration().bodyDeclarations()) {
|
||||
if (declObj instanceof MethodDeclaration md && md.getName().getIdentifier().equals(getterName)) {
|
||||
getter = md;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getter == null) {
|
||||
getter = context.findMethodDeclaration(td, getterName, true);
|
||||
}
|
||||
if (getter != null && getter.getBody() != null) {
|
||||
fieldValues.putAll(buildFieldValuesFromCIC(td, cic, context, this::evaluateMethodCallInConstructor));
|
||||
int lastDot = entryMethod.lastIndexOf('.');
|
||||
if (lastDot > 0) {
|
||||
String className = entryMethod.substring(0, lastDot);
|
||||
String methodName = entryMethod.substring(lastDot + 1);
|
||||
TypeDeclaration entryTd = context.getTypeDeclaration(className);
|
||||
if (entryTd != null) {
|
||||
MethodDeclaration entryMd = context.findMethodDeclaration(entryTd, methodName, false);
|
||||
if (entryMd != null && entryMd.getBody() != null) {
|
||||
// Skip trackSetterCallsBetween since getter call is not in entry method
|
||||
}
|
||||
}
|
||||
}
|
||||
String result = constantResolver.evaluateMethodBodyWithLocals(getter, fieldValues, context, new HashSet<>());
|
||||
if (result != null) {
|
||||
String returnType = getter.getReturnType2() != null ? getter.getReturnType2().toString() : null;
|
||||
if (returnType != null && !result.contains(".")) {
|
||||
int lastDotRet = returnType.lastIndexOf('.');
|
||||
String simpleReturnType = lastDotRet > 0 ? returnType.substring(lastDotRet + 1) : returnType;
|
||||
if (!simpleReturnType.equals("String") && !simpleReturnType.equals("Integer") && !simpleReturnType.equals("Long") && !simpleReturnType.equals("Boolean")) {
|
||||
result = simpleReturnType + "." + result;
|
||||
}
|
||||
}
|
||||
return Collections.singletonList(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected org.eclipse.jdt.core.dom.Expression findVariableInitializer(String methodFqn, String varName) {
|
||||
int lastDot = methodFqn.lastIndexOf('.');
|
||||
if (lastDot < 0) return null;
|
||||
String className = methodFqn.substring(0, lastDot);
|
||||
String methodName = methodFqn.substring(lastDot + 1);
|
||||
|
||||
TypeDeclaration td = context.getTypeDeclaration(className);
|
||||
if (td == null) return null;
|
||||
|
||||
MethodDeclaration md = context.findMethodDeclaration(td, methodName, false);
|
||||
if (md == null || md.getBody() == null) return null;
|
||||
|
||||
final org.eclipse.jdt.core.dom.Expression[] initExpr = {null};
|
||||
md.getBody().accept(new org.eclipse.jdt.core.dom.ASTVisitor() {
|
||||
@Override
|
||||
public boolean visit(org.eclipse.jdt.core.dom.VariableDeclarationStatement node) {
|
||||
for (Object fragObj : node.fragments()) {
|
||||
org.eclipse.jdt.core.dom.VariableDeclarationFragment frag = (org.eclipse.jdt.core.dom.VariableDeclarationFragment) fragObj;
|
||||
if (frag.getName().getIdentifier().equals(varName) && frag.getInitializer() != null) {
|
||||
initExpr[0] = frag.getInitializer();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return super.visit(node);
|
||||
}
|
||||
});
|
||||
return initExpr[0];
|
||||
}
|
||||
}
|
||||
@@ -540,341 +540,4 @@ public class HeuristicCallGraphEngine extends AbstractCallGraphEngine {
|
||||
});
|
||||
return foundReceiver[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TriggerPoint resolveTriggerPointParameters(TriggerPoint tp, List<String> path, Map<String, List<CallEdge>> callGraph) {
|
||||
if (path.size() < 2) return tp;
|
||||
|
||||
String event = tp.getEvent();
|
||||
if (event == null || event.isEmpty() || event.contains("\"")) return tp;
|
||||
|
||||
String currentParamName = event;
|
||||
String resolvedValue = event;
|
||||
String methodSuffix = "";
|
||||
boolean didThisSuperSubstitution = false;
|
||||
|
||||
String[] extractedEntry = extractMethodSuffix(currentParamName, methodSuffix);
|
||||
currentParamName = extractedEntry[0];
|
||||
methodSuffix = extractedEntry[1];
|
||||
|
||||
for (int i = path.size() - 1; i > 0; i--) {
|
||||
String target = path.get(i);
|
||||
String caller = path.get(i - 1);
|
||||
int paramIndex = getParameterIndex(target, currentParamName);
|
||||
if (paramIndex < 0) {
|
||||
java.util.Map<String, String> parameterValues = buildParameterValuesMap(caller, target, callGraph, path, i);
|
||||
String tracedVar = traceLocalVariable(target, currentParamName, parameterValues);
|
||||
if (tracedVar != null && !tracedVar.equals(currentParamName)) {
|
||||
String[] extractedTraced = extractMethodSuffix(tracedVar, methodSuffix);
|
||||
tracedVar = extractedTraced[0];
|
||||
methodSuffix = extractedTraced[1];
|
||||
currentParamName = tracedVar;
|
||||
resolvedValue = tracedVar + methodSuffix;
|
||||
paramIndex = getParameterIndex(target, currentParamName);
|
||||
}
|
||||
}
|
||||
if (paramIndex < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
List<CallEdge> edges = callGraph.get(caller);
|
||||
boolean found = false;
|
||||
if (edges != null) {
|
||||
for (CallEdge edge : edges) {
|
||||
if (edge.getTargetMethod().equals(target) || isHeuristicMatch(edge.getTargetMethod(), target)) {
|
||||
String expectedType = getParameterType(target, paramIndex);
|
||||
if (expectedType != null && paramIndex < edge.getArguments().size()) {
|
||||
String argValue = edge.getArguments().get(paramIndex);
|
||||
String actualType = null;
|
||||
if (argValue.contains(".") && !argValue.contains("(")) {
|
||||
String prefix = argValue.substring(0, argValue.lastIndexOf('.'));
|
||||
if (!prefix.equals("this") && !prefix.equals("super")) {
|
||||
actualType = prefix;
|
||||
}
|
||||
}
|
||||
if (actualType == null && !argValue.contains(".")) {
|
||||
actualType = getVariableDeclaredType(caller, argValue);
|
||||
}
|
||||
if (actualType != null && !isTypeCompatible(actualType, expectedType)) {
|
||||
log.debug("Call rejected due to type mismatch: {} calling {} with type {} instead of expected {}", caller, edge.getTargetMethod(), actualType, expectedType);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (paramIndex < edge.getArguments().size()) {
|
||||
String arg = edge.getArguments().get(paramIndex);
|
||||
if (arg != null) {
|
||||
String receiver = edge.getReceiver();
|
||||
if (receiver != null && !receiver.isEmpty() && ("this".equals(arg) || arg.startsWith("this.") || "super".equals(arg) || arg.startsWith("super."))) {
|
||||
String actualReceiver = receiver;
|
||||
boolean needPrevReceiver = "this".equals(arg) || arg.startsWith("this.");
|
||||
if (needPrevReceiver && !"this".equals(receiver) && !"super".equals(receiver)) {
|
||||
if (i - 1 > 0) {
|
||||
String prevCaller = path.get(i - 2);
|
||||
List<CallEdge> prevEdges = callGraph.get(prevCaller);
|
||||
if (prevEdges != null) {
|
||||
for (CallEdge prevEdge : prevEdges) {
|
||||
if (prevEdge.getTargetMethod().equals(caller) || isHeuristicMatch(prevEdge.getTargetMethod(), caller)) {
|
||||
actualReceiver = prevEdge.getReceiver();
|
||||
System.out.println("DEBUG TRACE: found prev edge, actualReceiver=" + actualReceiver);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ("this".equals(receiver) || "super".equals(receiver)) {
|
||||
if (i - 1 > 0) {
|
||||
String prevCaller = path.get(i - 2);
|
||||
List<CallEdge> prevEdges = callGraph.get(prevCaller);
|
||||
if (prevEdges != null) {
|
||||
for (CallEdge prevEdge : prevEdges) {
|
||||
if (prevEdge.getTargetMethod().equals(caller) || isHeuristicMatch(prevEdge.getTargetMethod(), caller)) {
|
||||
actualReceiver = prevEdge.getReceiver();
|
||||
System.out.println("DEBUG TRACE: found prev edge, actualReceiver=" + actualReceiver);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (actualReceiver != null && !actualReceiver.isEmpty()) {
|
||||
if ("this".equals(arg) || arg.startsWith("this.")) {
|
||||
arg = arg.replaceFirst("^this", actualReceiver);
|
||||
didThisSuperSubstitution = true;
|
||||
} else if ("super".equals(arg) || arg.startsWith("super.")) {
|
||||
arg = arg.replaceFirst("^super", actualReceiver);
|
||||
didThisSuperSubstitution = true;
|
||||
}
|
||||
System.out.println("DEBUG TRACE: after substitution arg=" + arg);
|
||||
}
|
||||
}
|
||||
String[] extractedArg = extractMethodSuffix(arg, methodSuffix);
|
||||
arg = extractedArg[0];
|
||||
methodSuffix = extractedArg[1];
|
||||
currentParamName = arg;
|
||||
resolvedValue = arg + methodSuffix;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) break;
|
||||
}
|
||||
|
||||
String entryMethod = path.get(0);
|
||||
int entryParamIndex = getParameterIndex(entryMethod, currentParamName);
|
||||
|
||||
if (resolvedValue != null && resolvedValue.contains(".") && !resolvedValue.contains("(") && !resolvedValue.contains(" ")) {
|
||||
TriggerPoint modifiedTp = TriggerPoint.builder()
|
||||
.event(resolvedValue)
|
||||
.className(tp.getClassName())
|
||||
.methodName(tp.getMethodName())
|
||||
.sourceFile(tp.getSourceFile())
|
||||
.sourceModule(tp.getSourceModule())
|
||||
.stateMachineId(tp.getStateMachineId())
|
||||
.sourceState(tp.getSourceState())
|
||||
.lineNumber(tp.getLineNumber())
|
||||
.polymorphicEvents(tp.getPolymorphicEvents() != null ? tp.getPolymorphicEvents() : new ArrayList<>())
|
||||
.build();
|
||||
return super.resolveTriggerPointParameters(modifiedTp, path, callGraph);
|
||||
}
|
||||
|
||||
if (entryParamIndex < 0) {
|
||||
if (methodSuffix.startsWith(".get") || methodSuffix.equals(".type") || methodSuffix.equals(".event") || methodSuffix.equals(".type()") || methodSuffix.equals(".event()")) {
|
||||
String localMethodName = methodSuffix.substring(1).replace("()", "");
|
||||
org.eclipse.jdt.core.dom.Expression localSetterExpr = traceLocalSetter(entryMethod, currentParamName, localMethodName);
|
||||
if (localSetterExpr != null) {
|
||||
List<String> setterEvents = new ArrayList<>();
|
||||
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())
|
||||
.className(tp.getClassName())
|
||||
.methodName(tp.getMethodName())
|
||||
.sourceFile(tp.getSourceFile())
|
||||
.sourceModule(tp.getSourceModule())
|
||||
.stateMachineId(tp.getStateMachineId())
|
||||
.sourceState(tp.getSourceState())
|
||||
.lineNumber(tp.getLineNumber())
|
||||
.polymorphicEvents(setterEvents)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasGetterOnReceiver = methodSuffix.startsWith(".get") && currentParamName != null
|
||||
&& !currentParamName.contains(".") && !currentParamName.contains("(") && !currentParamName.contains("new ");
|
||||
if (!hasGetterOnReceiver) {
|
||||
String tracedVar = traceLocalVariable(entryMethod, currentParamName);
|
||||
if (tracedVar != null && !tracedVar.equals(currentParamName)) {
|
||||
String[] extractedFinalTraced = extractMethodSuffix(tracedVar, methodSuffix);
|
||||
tracedVar = extractedFinalTraced[0];
|
||||
methodSuffix = extractedFinalTraced[1];
|
||||
currentParamName = tracedVar;
|
||||
resolvedValue = tracedVar + methodSuffix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String finalResolvedValue = resolvedValue;
|
||||
boolean hasGetterOnReceiver = methodSuffix.startsWith(".get") && currentParamName != null
|
||||
&& !currentParamName.contains(".") && !currentParamName.contains("(") && !currentParamName.contains("new ");
|
||||
if (hasGetterOnReceiver) {
|
||||
List<String> getterEvents = evaluateGetterOnReceiver(finalResolvedValue, methodSuffix, entryMethod, path, callGraph);
|
||||
if (getterEvents != null && !getterEvents.isEmpty()) {
|
||||
return TriggerPoint.builder()
|
||||
.event(tp.getEvent())
|
||||
.className(tp.getClassName())
|
||||
.methodName(tp.getMethodName())
|
||||
.sourceFile(tp.getSourceFile())
|
||||
.sourceModule(tp.getSourceModule())
|
||||
.stateMachineId(tp.getStateMachineId())
|
||||
.sourceState(tp.getSourceState())
|
||||
.lineNumber(tp.getLineNumber())
|
||||
.polymorphicEvents(getterEvents)
|
||||
.build();
|
||||
}
|
||||
// If we couldn't evaluate the getter, fall back to super with modified trigger point
|
||||
TriggerPoint modifiedTp = TriggerPoint.builder()
|
||||
.event(resolvedValue)
|
||||
.className(tp.getClassName())
|
||||
.methodName(tp.getMethodName())
|
||||
.sourceFile(tp.getSourceFile())
|
||||
.sourceModule(tp.getSourceModule())
|
||||
.stateMachineId(tp.getStateMachineId())
|
||||
.sourceState(tp.getSourceState())
|
||||
.lineNumber(tp.getLineNumber())
|
||||
.polymorphicEvents(tp.getPolymorphicEvents() != null ? tp.getPolymorphicEvents() : new ArrayList<>())
|
||||
.build();
|
||||
return super.resolveTriggerPointParameters(modifiedTp, path, callGraph);
|
||||
}
|
||||
|
||||
return super.resolveTriggerPointParameters(tp, path, callGraph);
|
||||
}
|
||||
|
||||
private List<String> evaluateGetterOnReceiver(String resolvedValue, String methodSuffix, String entryMethod, List<String> path, Map<String, List<CallEdge>> callGraph) {
|
||||
org.eclipse.jdt.core.dom.ASTParser exprParser = org.eclipse.jdt.core.dom.ASTParser.newParser(org.eclipse.jdt.core.dom.AST.JLS17);
|
||||
exprParser.setKind(org.eclipse.jdt.core.dom.ASTParser.K_EXPRESSION);
|
||||
exprParser.setSource(resolvedValue.toCharArray());
|
||||
org.eclipse.jdt.core.dom.ASTNode exprNode = exprParser.createAST(null);
|
||||
|
||||
if (exprNode instanceof org.eclipse.jdt.core.dom.MethodInvocation mi) {
|
||||
String getterName = mi.getName().getIdentifier();
|
||||
org.eclipse.jdt.core.dom.Expression receiver = mi.getExpression();
|
||||
String receiverName = null;
|
||||
String receiverType = null;
|
||||
|
||||
if (receiver instanceof org.eclipse.jdt.core.dom.SimpleName sn) {
|
||||
receiverName = sn.getIdentifier();
|
||||
receiverType = getVariableDeclaredType(entryMethod, receiverName);
|
||||
}
|
||||
|
||||
if (receiverType == null && path.size() > 1) {
|
||||
String callerMethod = path.get(1);
|
||||
receiverType = getVariableDeclaredType(callerMethod, receiverName);
|
||||
}
|
||||
|
||||
if (receiverType != null) {
|
||||
String simpleReceiverType = receiverType;
|
||||
if (receiverType.contains("<")) {
|
||||
String rawType = receiverType.substring(0, receiverType.indexOf('<'));
|
||||
if (rawType.equals("List") || rawType.equals("Set") || rawType.equals("Collection") || rawType.equals("Iterable") || context.getTypeDeclaration(rawType) == null) {
|
||||
int start = receiverType.indexOf('<');
|
||||
int end = receiverType.lastIndexOf('>');
|
||||
if (start >= 0 && end > start) {
|
||||
simpleReceiverType = receiverType.substring(start + 1, end);
|
||||
}
|
||||
} else {
|
||||
simpleReceiverType = rawType;
|
||||
}
|
||||
}
|
||||
TypeDeclaration td = context.getTypeDeclaration(simpleReceiverType);
|
||||
if (td != null) {
|
||||
Map<String, String> fieldValues = new HashMap<>();
|
||||
String varName = receiverName;
|
||||
org.eclipse.jdt.core.dom.Expression initExpr = findVariableInitializer(entryMethod, varName);
|
||||
if (initExpr instanceof org.eclipse.jdt.core.dom.MethodInvocation initMi) {
|
||||
initExpr = unwrapMethodInvocation(initMi, 0);
|
||||
}
|
||||
if (!(initExpr instanceof org.eclipse.jdt.core.dom.ClassInstanceCreation cic)) {
|
||||
return null;
|
||||
}
|
||||
MethodDeclaration getter = null;
|
||||
if (cic.getAnonymousClassDeclaration() != null) {
|
||||
for (Object declObj : cic.getAnonymousClassDeclaration().bodyDeclarations()) {
|
||||
if (declObj instanceof MethodDeclaration md && md.getName().getIdentifier().equals(getterName)) {
|
||||
getter = md;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getter == null) {
|
||||
getter = context.findMethodDeclaration(td, getterName, true);
|
||||
}
|
||||
if (getter != null && getter.getBody() != null) {
|
||||
fieldValues.putAll(buildFieldValuesFromCIC(td, cic, context, this::evaluateMethodCallInConstructor));
|
||||
int lastDot = entryMethod.lastIndexOf('.');
|
||||
if (lastDot > 0) {
|
||||
String className = entryMethod.substring(0, lastDot);
|
||||
String methodName = entryMethod.substring(lastDot + 1);
|
||||
TypeDeclaration entryTd = context.getTypeDeclaration(className);
|
||||
if (entryTd != null) {
|
||||
MethodDeclaration entryMd = context.findMethodDeclaration(entryTd, methodName, false);
|
||||
if (entryMd != null && entryMd.getBody() != null) {
|
||||
// Skip trackSetterCallsBetween since getter call is not in entry method
|
||||
}
|
||||
}
|
||||
}
|
||||
String result = constantResolver.evaluateMethodBodyWithLocals(getter, fieldValues, context, new HashSet<>());
|
||||
if (result != null) {
|
||||
String returnType = getter.getReturnType2() != null ? getter.getReturnType2().toString() : null;
|
||||
if (returnType != null && !result.contains(".")) {
|
||||
int lastDotRet = returnType.lastIndexOf('.');
|
||||
String simpleReturnType = lastDotRet > 0 ? returnType.substring(lastDotRet + 1) : returnType;
|
||||
if (!simpleReturnType.equals("String") && !simpleReturnType.equals("Integer") && !simpleReturnType.equals("Long") && !simpleReturnType.equals("Boolean")) {
|
||||
result = simpleReturnType + "." + result;
|
||||
}
|
||||
}
|
||||
return Collections.singletonList(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private org.eclipse.jdt.core.dom.Expression findVariableInitializer(String methodFqn, String varName) {
|
||||
int lastDot = methodFqn.lastIndexOf('.');
|
||||
if (lastDot < 0) return null;
|
||||
String className = methodFqn.substring(0, lastDot);
|
||||
String methodName = methodFqn.substring(lastDot + 1);
|
||||
|
||||
TypeDeclaration td = context.getTypeDeclaration(className);
|
||||
if (td == null) return null;
|
||||
|
||||
MethodDeclaration md = context.findMethodDeclaration(td, methodName, false);
|
||||
if (md == null || md.getBody() == null) return null;
|
||||
|
||||
final org.eclipse.jdt.core.dom.Expression[] initExpr = {null};
|
||||
md.getBody().accept(new org.eclipse.jdt.core.dom.ASTVisitor() {
|
||||
@Override
|
||||
public boolean visit(org.eclipse.jdt.core.dom.VariableDeclarationStatement node) {
|
||||
for (Object fragObj : node.fragments()) {
|
||||
org.eclipse.jdt.core.dom.VariableDeclarationFragment frag = (org.eclipse.jdt.core.dom.VariableDeclarationFragment) fragObj;
|
||||
if (frag.getName().getIdentifier().equals(varName) && frag.getInitializer() != null) {
|
||||
initExpr[0] = frag.getInitializer();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return super.visit(node);
|
||||
}
|
||||
});
|
||||
return initExpr[0];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user