use of com.android.tools.idea.experimental.codeanalysis.datastructs.graph.BlockGraph in project android by JetBrains.
the class CFGBuilder method dfsPsiForeachStatementBuilder.
/**
* Build nodes for "for each" loops
* @param statement The foreach statement
* @param label The label for this loop. In case of labeled break.
*/
public void dfsPsiForeachStatementBuilder(@NotNull PsiForeachStatement statement, @Nullable PsiIdentifier label) {
PsiStatement loopBody = statement.getBody();
int loopType;
LoopBranchingNodeImpl loopNode;
GraphNode conditionCheckEntry;
ConditionCheckNode conditionCheckExit;
GraphNode postLoopEntry;
GraphNode postLoopExit;
loopType = LoopBranchingNode.FOREACH_LOOP;
//for (Type iter : val);
//The iter is the iterParam here
//The val is the iterValue here.
PsiParameter iterParam = statement.getIterationParameter();
PsiExpression iterValue = statement.getIteratedValue();
if (iterParam == null) {
//TODO: Log it and return
return;
}
if (iterParam == null) {
//TODO: Log it and return
return;
}
Value iterV = dfsExpressionBuilder(iterValue);
Param iterP = new ParamImpl(iterParam);
loopNode = new LoopBranchingNodeImpl(this.mGraph, loopType);
connectCurrentWorkingNode(loopNode);
pushLoopNode(loopNode, label);
BlockGraph loopBodyGraph = loopbodyBuilder(loopBody, statement, iterParam, iterP);
loopNode.setLoopBody(loopBodyGraph);
loopNode.setForeachIteratorParam(iterP);
loopNode.setForeachIteratorValue(iterV);
GraphNodeUtil.connectGraphNode(loopNode, loopBodyGraph.getEntryNode());
GraphNodeUtil.connectGraphNode(loopNode, loopBodyGraph.getExitNode());
GraphNodeUtil.connectGraphNode(loopBodyGraph.getExitNode(), loopNode);
loopNode.connectSpecialNodes();
curWorkingNodeList.clear();
curWorkingNodeList.add(loopBodyGraph.getExitNode());
popLoopNode();
}
use of com.android.tools.idea.experimental.codeanalysis.datastructs.graph.BlockGraph in project android by JetBrains.
the class CFGBuilder method resolveParam.
/**
* Resolve the parameter at the current context.
* @param param The parameter
* @return The PsiCFG wrapper for the parameter
*/
@Nullable
private Param resolveParam(@NotNull PsiParameter param) {
Graph graph = this.mGraph;
if (graph instanceof BlockGraph) {
Param p = ((BlockGraph) graph).getParamFromPsiParameter(param);
if (p == null) {
if (graph instanceof MethodGraph) {
MethodGraph methodGraph = (MethodGraph) graph;
PsiCFGDebugUtil.LOG.warning("Parameter " + param.getName() + " does not exist in method " + methodGraph.getPsiCFGMethod().getName() + " in class " + this.containerClass.getQualifiedClassName());
} else {
PsiStatement psiStmt = ((BlockGraph) graph).getParentStmt();
PsiCFGDebugUtil.LOG.warning("Parameter " + param.getName() + " does not exist in context " + psiStmt.getText() + " in class " + this.containerClass.getQualifiedClassName());
}
}
return p;
}
PsiCFGDebugUtil.LOG.warning("Parameter " + param.getName() + " does not exist, the graph is not" + " a block graph");
return null;
}
use of com.android.tools.idea.experimental.codeanalysis.datastructs.graph.BlockGraph in project android by JetBrains.
the class CFGBuilder method dfsDeclarationStatementBuilder.
/**
* Declaration Statement will not return a value, therefore always return null;
*
* @param resultArray
* @param currentDeclStmt
* @return
*/
public Value dfsDeclarationStatementBuilder(PsiDeclarationStatement currentDeclStmt) {
PsiElement[] retElements = currentDeclStmt.getDeclaredElements();
for (PsiElement curElement : retElements) {
if (curElement == null) {
PsiCFGDebugUtil.LOG.warning("element in DeclarationStatement " + currentDeclStmt.getText() + " is null");
continue;
}
if (curElement instanceof PsiLocalVariable) {
//So it is a local variable
PsiLocalVariable curLocal = (PsiLocalVariable) curElement;
PsiType localType = curLocal.getType();
//Generate the decl statement
DeclarationStmtImpl newDecl = new DeclarationStmtImpl(localType, curLocal, currentDeclStmt);
connectGeneratedStmt(newDecl);
if (this.mGraph instanceof BlockGraph) {
((BlockGraph) (this.mGraph)).addLocal(curLocal, (LocalImpl) newDecl.getLocal());
}
if (curLocal.hasInitializer()) {
//Generate Statement for the initializer
PsiExpression initializer = curLocal.getInitializer();
Value initExpr = dfsExpressionBuilder(initializer);
AssignStmtImpl initializerStmt = new AssignStmtImpl(true, null, JavaTokenType.EQ);
LocalImpl localExpr = (LocalImpl) newDecl.getLocal();
initializerStmt.setROp(initExpr);
initializerStmt.setLOp(localExpr);
connectGeneratedStmt(initializerStmt);
}
} else if (curElement instanceof PsiClass) {
//It declares a nested class
mScene.getOrCreateNestedClass((PsiClass) curElement, this.containerClass, retrieveDeclaringMethod(), this.mGraph);
} else {
PsiCFGDebugUtil.LOG.warning("element " + curElement.getText() + " in DeclarationStmt " + currentDeclStmt.getText() + " cannot be resolved");
}
}
return null;
}
use of com.android.tools.idea.experimental.codeanalysis.datastructs.graph.BlockGraph in project android by JetBrains.
the class CFGBuilder method dfsPsiForStatementBuilder.
/**
* Build nodes for "for" loop.
* @param statement The PsiForStatement
* @param label The identifier of the label, can be null.
*/
public void dfsPsiForStatementBuilder(@NotNull PsiForStatement statement, @Nullable PsiIdentifier label) {
PsiStatement loopBody = statement.getBody();
int loopType;
LoopBranchingNodeImpl loopNode;
GraphNode conditionCheckEntry;
ConditionCheckNode conditionCheckExit;
GraphNode postLoopEntry;
GraphNode postLoopExit;
loopType = LoopBranchingNode.FOR_LOOP;
//Evaluate the init code
PsiForStatement forStmt = statement;
PsiStatement initStmt = forStmt.getInitialization();
if (initStmt != null) {
buildNonBranchingStatements(initStmt);
}
loopNode = new LoopBranchingNodeImpl(this.mGraph, loopType);
connectCurrentWorkingNode(loopNode);
//Push this loopNode into the stack
pushLoopNode(loopNode, label);
//Eval the condition check
PsiExpression psiConditionCheckCode = forStmt.getCondition();
Value finalCheckVal = dfsExpressionBuilder(psiConditionCheckCode);
//Build the final condition check for this loop
conditionCheckExit = new ConditionCheckNodeImpl(this.mGraph, finalCheckVal);
if (loopNode.getOut().length == 0) {
//The dummy loop node does not have any out edges
//In this case the conditionCheckEntry is the same
//as the conditionCheckExit
conditionCheckEntry = conditionCheckExit;
} else {
//At this point the dummy LoopNode is connected to the entry
//of the condition check code.
conditionCheckEntry = loopNode.getOut()[0];
}
connectCurrentWorkingNode(conditionCheckExit);
//Build the loop body
BlockGraph loopBodyGraph = loopbodyBuilder(loopBody, statement);
//Connect the condition check code true branch to loop entry
GraphNodeUtil.connectGraphNode(conditionCheckExit.getTrueBranch(), loopBodyGraph.getEntryNode());
curWorkingNodeList.clear();
curWorkingNodeList.add(loopBodyGraph.getExitNode());
//Eval Post loop code
PsiStatement postLoopUpdateStatment = forStmt.getUpdate();
buildNonBranchingStatements(postLoopUpdateStatment);
postLoopEntry = loopBodyGraph.getExitNode().getOut()[0];
postLoopExit = curWorkingNodeList.get(0);
//Connect the post loop to the condition check entry
connectCurrentWorkingNode(conditionCheckEntry);
curWorkingNodeList.clear();
curWorkingNodeList.add(conditionCheckExit.getFalseBranch());
loopNode.setConditionCheckEntry(conditionCheckEntry);
loopNode.setConditionCheckExitNode(conditionCheckExit);
loopNode.setPostLoopEntryNode(postLoopEntry);
loopNode.setPostLoopExitNode(postLoopExit);
loopNode.setLoopBody(loopBodyGraph);
//For loop build complete
//Process the break and continue nodes
loopNode.connectSpecialNodes();
popLoopNode();
}
use of com.android.tools.idea.experimental.codeanalysis.datastructs.graph.BlockGraph in project android by JetBrains.
the class CFGBuilder method resolveLocal.
/**
* Resolve the local variable at the current context
* @param localVar The local
* @return The PsiCFG wrapper for the local.
*/
@Nullable
private Local resolveLocal(@NotNull PsiLocalVariable localVar) {
Local l = this.mGraph.getLocalFromPsiLocal(localVar);
if (l != null) {
return l;
}
if (this.containerClass.isNested()) {
//Nested class
BlockGraph parentBlock = this.containerClass.getDeclaringBlock();
l = parentBlock.getLocalFromPsiLocal(localVar);
}
if (l == null) {
PsiCFGDebugUtil.LOG.warning(String.format("Local %s cannot be resolved in Class %s", localVar.getText(), this.containerClass.getQualifiedClassName()));
}
return l;
}
Aggregations