use of com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGClass in project android by JetBrains.
the class CFGBuilder method dfsPsiLambdaExpressionBuilder.
/**
* The purpose of this method is to transform ()->{} in method invocation
* or assignment expression into new InterfaceName(Type Arg){ @Override Method(){} };
*
* @param expression
* @return
*/
public Value dfsPsiLambdaExpressionBuilder(PsiLambdaExpression expression) {
PsiType interfaceType = expression.getFunctionalInterfaceType();
PsiClass interfaceClassRef = null;
if (interfaceType == null) {
//The SAM type interface cannot be found by intelliJ
//There is no way to resolve the SAM type by ourselves.
//Just return a dummy here.
PsiCFGDebugUtil.LOG.warning("Lambda Expression: " + expression.getText() + " cannot be resolved");
return new DummyRef(expression.getType(), expression);
}
if (interfaceType instanceof PsiClassType) {
interfaceClassRef = ((PsiClassType) interfaceType).resolve();
} else {
PsiCFGDebugUtil.LOG.warning("Lambda Expression: " + expression.getText() + " type is not interface");
PsiCFGDebugUtil.LOG.warning("Type: " + interfaceType.getClass().getSimpleName());
return new DummyRef(expression.getType(), expression);
}
//Create the wrapper class for the lambda expression
PsiCFGClass lambdaWrapperClass = mScene.createLambdaAnonymousClass(expression, interfaceClassRef, this.containerClass);
//Create new expression
NewExprImpl newExprImpl = new NewExprImpl(interfaceType, expression);
newExprImpl.setBaseClass(lambdaWrapperClass);
//Lambda expression does not have constructor arguments
SynthesizedLocal synLocal = createSynthesizeTemporalVariable(newExprImpl);
return synLocal;
}
use of com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGClass in project android by JetBrains.
the class CFGBuilder method dfsLHSReferenceExpressionBuilder.
/**
* @param expression
* @return
*/
public Value dfsLHSReferenceExpressionBuilder(PsiReferenceExpression expression) {
PsiElement target = expression.resolve();
if (target == null) {
PsiCFGDebugUtil.LOG.warning("ReferenceExpression cannot be resolved: " + expression.getText());
}
if (target instanceof PsiLocalVariable) {
Local l = resolveLocal((PsiLocalVariable) target);
//return this.mGraph.getLocalFromPsiLocal((PsiLocalVariable)target);
if (l == null) {
return new DummyRef(expression.getType(), expression);
} else {
return l;
}
}
//Second, determine if the ReferenceExpression is refering to a param
if (target instanceof PsiParameter) {
Param p = resolveParam((PsiParameter) target);
if (p == null) {
return new DummyRef(expression.getType(), expression);
} else {
return p;
}
}
//So now it refers to a field/method/class
PsiExpression qualifier = expression.getQualifierExpression();
if (qualifier == null) {
}
if (target instanceof PsiField) {
PsiField fieldTarget = (PsiField) target;
PsiCFGClass cfgClass = mScene.getOrCreateCFGClass(fieldTarget.getContainingClass());
PsiCFGField cfgField = cfgClass.getField(fieldTarget.getName());
if (qualifier == null) {
//TODO: Inner Class/ Anonymous Class might have difference reference to this.
return processLHSRefExprWithTgtPsiFieldQualifierNull(fieldTarget, cfgClass, cfgField, expression);
} else if (qualifier instanceof PsiThisExpression) {
//this.sth
PsiCFGClass thisClass = this.containerClass;
PsiThisExpression thisPsiExpression = (PsiThisExpression) qualifier;
ThisRefImpl thisRefImpl = new ThisRefImpl(thisPsiExpression, thisClass, fieldTarget.getType());
InstanceFieldRefImpl instanceFieldRef = new InstanceFieldRefImpl(fieldTarget.getType(), cfgField, expression);
instanceFieldRef.setBase(thisRefImpl);
//SynthesizedLocal synLocal = createSynthesizeTemporalVariable(instanceFieldRef);
return instanceFieldRef;
} else if (qualifier instanceof PsiSuperExpression) {
//super.sth
//Should not happen here
PsiCFGDebugUtil.LOG.warning("Super.field happened at expression: " + expression.getText());
return new DummyRef(expression.getType(), expression);
} else if (qualifier instanceof PsiReferenceExpression) {
PsiElement resolveOfQualifier = ((PsiReferenceExpression) qualifier).resolve();
if (resolveOfQualifier instanceof PsiClass) {
//Consider it is a static reference
return createLHSStaticRefExpression(fieldTarget.getType(), cfgField, expression);
} else if (resolveOfQualifier instanceof PsiReferenceExpression) {
//qualifier is a PsiReferenceExpression
Value qualifierValue = dfsRHSReferenceExpressionBuilder((PsiReferenceExpression) resolveOfQualifier);
InstanceFieldRef instanceFieldRef = new InstanceFieldRefImpl(fieldTarget.getType(), cfgField, expression);
instanceFieldRef.setBase(qualifierValue);
return instanceFieldRef;
} else if (resolveOfQualifier instanceof PsiLocalVariable) {
//Qualifier is a local
//Local.field
Local local = resolveLocal((PsiLocalVariable) resolveOfQualifier);
if (local == null) {
local = new LocalImpl(qualifier.getType(), (PsiLocalVariable) resolveOfQualifier);
}
InstanceFieldRef instanceFieldRef = new InstanceFieldRefImpl(fieldTarget.getType(), cfgField, expression);
instanceFieldRef.setBase(local);
return instanceFieldRef;
} else if (resolveOfQualifier instanceof PsiField || resolveOfQualifier instanceof PsiParameter) {
Value field = dfsRHSReferenceExpressionBuilder((PsiReferenceExpression) qualifier);
InstanceFieldRef instanceFieldRef = new InstanceFieldRefImpl(fieldTarget.getType(), cfgField, expression);
instanceFieldRef.setBase(field);
return instanceFieldRef;
} else {
PsiCFGDebugUtil.LOG.warning("Unknown resolve type of qualifer ");
PsiCFGDebugUtil.debugOutputPsiElement(resolveOfQualifier);
}
} else if (qualifier instanceof PsiMethodCallExpression) {
//a.method().field
Value methodCallLocal = dfsPsiMethodCallExpressionBuilder((PsiMethodCallExpression) qualifier);
InstanceFieldRefImpl instanceFieldRef = new InstanceFieldRefImpl(fieldTarget.getType(), cfgField, expression);
instanceFieldRef.setBase(methodCallLocal);
return instanceFieldRef;
} else {
//Unsupported Qualifier
PsiCFGDebugUtil.LOG.warning("Unsupported Qualifier in expression: " + expression.getText());
PsiCFGDebugUtil.debugOutputPsiElement(qualifier);
}
} else if (target instanceof PsiMethod) {
PsiCFGDebugUtil.LOG.info("Refering to a method: " + ((PsiMethod) target).getName());
} else {
PsiCFGDebugUtil.LOG.info("Other circumstances: target of the Reference Expression is : " + target.getClass().getSimpleName());
}
DummyRef ref = new DummyRef(expression.getType(), expression);
return ref;
}
use of com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGClass in project android by JetBrains.
the class CFGBuilder method dfsThisExpressionBuilder.
public Value dfsThisExpressionBuilder(PsiThisExpression expression) {
PsiType thisType = expression.getType();
PsiClassType classType = null;
PsiCFGClass thisCFGClass = this.containerClass;
if (thisType instanceof PsiClassType) {
classType = (PsiClassType) thisType;
} else {
PsiCFGDebugUtil.LOG.warning("PsiThisExpression's type is NOT classType :" + thisType.getClass().getSimpleName());
}
if (classType != null) {
PsiClass classPsiRef = classType.resolve();
thisCFGClass = mScene.getOrCreateCFGClass(classPsiRef);
}
ThisRefImpl thisRef = new ThisRefImpl(expression, thisCFGClass, thisType);
return thisRef;
}
use of com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGClass in project android by JetBrains.
the class CallgraphBuilder method performCHAForInvocationSite.
public void performCHAForInvocationSite(GraphNode node, PsiType receiverType, PsiCFGMethod targetMethod) {
//Only Object can perform instance invoke
if (!(receiverType instanceof PsiClassType)) {
//The reciever type is not an object
PsiCFGDebugUtil.LOG.warning("The Receiver's type is not PsiClassType " + receiverType.getCanonicalText() + " " + targetMethod.getName());
} else {
PsiClassType receiverClassType = (PsiClassType) receiverType;
PsiClass psiClassRef = receiverClassType.resolve();
PsiCFGClass receiverClass = mScene.getPsiCFGClass(psiClassRef);
if (receiverClass == null) {
PsiCFGDebugUtil.LOG.warning("The Receiver's CFGClass is not resolved during " + "the CFG construction " + psiClassRef.getQualifiedName());
return;
}
//Find first concrete method to the top
//It may not exist
PsiCFGPartialMethodSignature methodSignature = targetMethod.getSignature();
PsiCFGMethod nearestConcreteMethodFromTop = getNearestConcreteMethod(receiverClass, methodSignature);
if (nearestConcreteMethodFromTop != null) {
addToCallGraph(node, nearestConcreteMethodFromTop);
}
//Find concrete method to the leaf
ArrayList<PsiCFGMethod> methodList = Lists.newArrayList();
recursivelyQueryConcreteMethodFromChildrenWithCache(methodList, receiverClass, methodSignature);
for (PsiCFGMethod concreteMethodFromSubClass : methodList) {
addToCallGraph(node, concreteMethodFromSubClass);
}
}
}
use of com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGClass in project android by JetBrains.
the class PsiCFGAnalysisUtil method performStage4.
/**
* Because the list of library classes is not complete
* before the construction of control flow graph in the Stage 2,
* this stage is created to put the class hierarchy info
* into the PsiCFGClasses
*/
public void performStage4() {
PsiCFGClass[] libraryClasses = mScene.getAllLibraryClasses();
Set<PsiClass> LibraryClassSet = mScene.getAllLibraryClassPsiSet();
for (PsiCFGClass curLibClass : libraryClasses) {
PsiClass psiRef = curLibClass.getPsiClass();
if (psiRef == null) {
continue;
}
PsiClass superRef = psiRef.getSuperClass();
PsiClass[] interfaceRefs = psiRef.getInterfaces();
if (LibraryClassSet.contains(superRef)) {
PsiCFGClass superCFGClass = mScene.getOrCreateCFGClass(superRef);
curLibClass.setSuperClass(superCFGClass);
superCFGClass.addSubClass(curLibClass);
}
setInterfacesIfInLibrary(curLibClass, interfaceRefs, LibraryClassSet);
}
}
Aggregations