Search in sources :

Example 21 with PsiCFGClass

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;
}
Also used : PsiCFGClass(com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGClass)

Example 22 with PsiCFGClass

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;
}
Also used : PsiCFGField(com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGField) PsiCFGClass(com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGClass)

Example 23 with PsiCFGClass

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;
}
Also used : PsiCFGClass(com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGClass)

Example 24 with PsiCFGClass

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);
        }
    }
}
Also used : PsiCFGMethod(com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGMethod) PsiClassType(com.intellij.psi.PsiClassType) PsiCFGPartialMethodSignature(com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGPartialMethodSignature) PsiClass(com.intellij.psi.PsiClass) PsiCFGClass(com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGClass)

Example 25 with PsiCFGClass

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);
    }
}
Also used : PsiCFGClass(com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGClass)

Aggregations

PsiCFGClass (com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGClass)28 PsiCFGMethod (com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGMethod)8 PsiCFGPartialMethodSignature (com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGPartialMethodSignature)3 PsiCFGField (com.android.tools.idea.experimental.codeanalysis.datastructs.PsiCFGField)2 PsiClassType (com.intellij.psi.PsiClassType)2 MethodGraph (com.android.tools.idea.experimental.codeanalysis.datastructs.graph.MethodGraph)1 PsiCFGAnalysisUtil (com.android.tools.idea.experimental.codeanalysis.utils.PsiCFGAnalysisUtil)1 Pair (com.intellij.openapi.util.Pair)1 PsiClass (com.intellij.psi.PsiClass)1 BufferedWriter (java.io.BufferedWriter)1 File (java.io.File)1 FileWriter (java.io.FileWriter)1 IOException (java.io.IOException)1