public void visitAssertStatement(GrAssertStatement assertStatement) { final InstructionImpl assertInstruction = startNode(assertStatement); final GrExpression assertion = assertStatement.getAssertion(); if (assertion != null) { assertion.accept(this); InstructionImpl positiveHead = myHead; List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(assertStatement); if (!negations.isEmpty()) { interruptFlow(); reduceAllNegationsIntoInstruction(assertStatement, negations); } GrExpression errorMessage = assertStatement.getErrorMessage(); if (errorMessage != null) { errorMessage.accept(this); } addNode(new ThrowingInstruction(assertStatement)); final PsiType type = TypesUtil.createTypeByFQClassName( CommonClassNames.JAVA_LANG_ASSERTION_ERROR, assertStatement); ExceptionInfo info = findCatch(type); if (info != null) { info.myThrowers.add(myHead); } else { addPendingEdge(null, myHead); } myHead = positiveHead; } finishNode(assertInstruction); }
@Override public void visitCaseSection(GrCaseSection caseSection) { for (GrCaseLabel label : caseSection.getCaseLabels()) { GrExpression value = label.getValue(); if (value != null) { value.accept(this); } } final GrStatement[] statements = caseSection.getStatements(); // infer 'may be return' position int i; for (i = statements.length - 1; i >= 0 && statements[i] instanceof GrBreakStatement; i--) {} for (int j = 0; j < statements.length; j++) { GrStatement statement = statements[j]; statement.accept(this); if (j == i) handlePossibleReturn(statement); } if (myHead != null) { addPendingEdge(caseSection, myHead); } }
@Override public void visitUnaryExpression(GrUnaryExpression expression) { final GrExpression operand = expression.getOperand(); if (operand == null) return; if (expression.getOperationTokenType() != mLNOT) { operand.accept(this); visitCall(expression); return; } ConditionInstruction cond = new ConditionInstruction(expression); addNodeAndCheckPending(cond); registerCondition(cond); operand.accept(this); visitCall(expression); myConditions.removeFirstOccurrence(cond); List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(expression); InstructionImpl head = myHead; addNodeAndCheckPending(new PositiveGotoInstruction(expression, cond)); handlePossibleReturn(expression); addPendingEdge(expression, myHead); if (negations.isEmpty()) { myHead = head; } else { myHead = reduceAllNegationsIntoInstruction(expression, negations); } }
private void addForLoopBreakingEdge(GrForStatement forStatement, @Nullable GrForClause clause) { if (clause instanceof GrTraditionalForClause) { final GrExpression condition = ((GrTraditionalForClause) clause).getCondition(); if (condition != null) { condition.accept(this); if (!alwaysTrue(condition)) { addPendingEdge(forStatement, myHead); // break cycle } } } else { addPendingEdge(forStatement, myHead); // break cycle } }
public void visitReturnStatement(GrReturnStatement returnStatement) { boolean isNodeNeeded = myHead == null || myHead.getElement() != returnStatement; final GrExpression value = returnStatement.getReturnValue(); if (value != null) value.accept(this); if (isNodeNeeded) { InstructionImpl returnInstruction = startNode(returnStatement); addPendingEdge(null, myHead); finishNode(returnInstruction); } else { addPendingEdge(null, myHead); } interruptFlow(); }
public void visitAssignmentExpression(GrAssignmentExpression expression) { GrExpression lValue = expression.getLValue(); if (expression.getOperationTokenType() != mASSIGN) { if (lValue instanceof GrReferenceExpression && myPolicy.isReferenceAccepted((GrReferenceExpression) lValue)) { String referenceName = ((GrReferenceExpression) lValue).getReferenceName(); if (referenceName != null) { addNodeAndCheckPending(new ReadWriteVariableInstruction(referenceName, lValue, READ)); } } } GrExpression rValue = expression.getRValue(); if (rValue != null) { rValue.accept(this); lValue.accept(this); } }
@Nullable private static PsiType getNominalTypeNoRecursion(@NotNull final GrExpression expression) { if (expression instanceof GrNewExpression) { return expression.getType(); } else if (expression instanceof GrReferenceExpression && ((GrReferenceExpression) expression).getQualifier() == null) { return getTypeByRef((GrReferenceExpression) expression); } return null; }
@Override public void visitElvisExpression(GrElvisExpression expression) { GrExpression condition = expression.getCondition(); GrExpression elseBranch = expression.getElseBranch(); condition.accept(this); List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(expression); InstructionImpl head = myHead; handlePossibleReturn(condition); addPendingEdge(expression, myHead); myHead = head; if (elseBranch != null) { head = reduceAllNegationsIntoInstruction(expression, negations); if (head != null) myHead = head; elseBranch.accept(this); handlePossibleReturn(elseBranch); } }
public void visitThrowStatement(GrThrowStatement throwStatement) { final GrExpression exception = throwStatement.getException(); if (exception == null) return; exception.accept(this); final InstructionImpl throwInstruction = new ThrowingInstruction(throwStatement); addNodeAndCheckPending(throwInstruction); interruptFlow(); final PsiType type = getNominalTypeNoRecursion(exception); if (type != null) { ExceptionInfo info = findCatch(type); if (info != null) { info.myThrowers.add(throwInstruction); } else { addPendingEdge(null, throwInstruction); } } else { addPendingEdge(null, throwInstruction); } }
private static boolean textOfExpressionsIsEquivalent( GrExpression expToCompare1, GrExpression expToCompare2) { final String text1 = expToCompare1.getText(); final String text2 = expToCompare2.getText(); return text1.equals(text2); }
@SuppressWarnings({"ConstantConditions"}) public static boolean expressionsAreEquivalent( @Nullable GrExpression exp1, @Nullable GrExpression exp2) { if (exp1 == null && exp2 == null) { return true; } if (exp1 == null || exp2 == null) { return false; } GrExpression expToCompare1 = (GrExpression) PsiUtil.skipParentheses(exp1, false); GrExpression expToCompare2 = (GrExpression) PsiUtil.skipParentheses(exp2, false); final int type1 = getExpressionType(expToCompare1); final int type2 = getExpressionType(expToCompare2); if (type1 != type2) { return false; } switch (type1) { case THIS_EXPRESSION: case SUPER_EXPRESSION: return true; case LITERAL_EXPRESSION: case REFERENCE_EXPRESSION: final String text1 = expToCompare1.getText(); final String text2 = expToCompare2.getText(); return text1.equals(text2); case CALL_EXPRESSION: return methodCallExpressionsAreEquivalent( (GrMethodCall) expToCompare1, (GrMethodCall) expToCompare2); case NEW_EXPRESSION: return newExpressionsAreEquivalent( (GrNewExpression) expToCompare1, (GrNewExpression) expToCompare2); case ARRAY_LITERAL_EXPRESSION: return arrayDeclarationsAreEquivalent( (GrArrayDeclaration) expToCompare1, (GrArrayDeclaration) expToCompare2); case PREFIX_EXPRESSION: return prefixExpressionsAreEquivalent( (GrUnaryExpression) expToCompare1, (GrUnaryExpression) expToCompare2); case POSTFIX_EXPRESSION: return postfixExpressionsAreEquivalent( (GrUnaryExpression) expToCompare1, (GrUnaryExpression) expToCompare2); case BINARY_EXPRESSION: return binaryExpressionsAreEquivalent( (GrBinaryExpression) expToCompare1, (GrBinaryExpression) expToCompare2); case ASSIGNMENT_EXPRESSION: return assignmentExpressionsAreEquivalent( (GrAssignmentExpression) expToCompare1, (GrAssignmentExpression) expToCompare2); case CONDITIONAL_EXPRESSION: return conditionalExpressionsAreEquivalent( (GrConditionalExpression) expToCompare1, (GrConditionalExpression) expToCompare2); case ELVIS_EXPRESSION: return elvisExpressionsAreEquivalent( (GrElvisExpression) expToCompare1, (GrElvisExpression) expToCompare2); case RANGE_EXPRESSION: return rangeExpressionsAreEquivalent( (GrRangeExpression) expToCompare1, (GrRangeExpression) expToCompare2); case TYPE_CAST_EXPRESSION: return typecastExpressionsAreEquivalent( (GrTypeCastExpression) expToCompare1, (GrTypeCastExpression) expToCompare2); case SAFE_CAST_EXPRESSION: return safecastExpressionsAreEquivalent( (GrSafeCastExpression) expToCompare1, (GrSafeCastExpression) expToCompare2); case INSTANCEOF_EXPRESSION: return instanceofExpressionsAreEquivalent( (GrInstanceOfExpression) expToCompare1, (GrInstanceOfExpression) expToCompare2); case INDEX_EXPRESSION: return indexExpressionsAreEquivalent( (GrIndexProperty) expToCompare1, (GrIndexProperty) expToCompare2); case LIST_OR_MAP_EXPRESSION: return listOrMapExpressionsAreEquivalent( (GrListOrMap) expToCompare1, (GrListOrMap) expToCompare2); case CLOSABLE_BLOCK_EXPRESSION: return closableBlockExpressionsAreEquivalent( (GrClosableBlock) expToCompare1, (GrClosableBlock) expToCompare2); case PROPERTY_SELECTION_EXPRESSION: return textOfExpressionsIsEquivalent(expToCompare1, expToCompare2); // todo default: return false; } }
@Override public void visitBinaryExpression(GrBinaryExpression expression) { final GrExpression left = expression.getLeftOperand(); final GrExpression right = expression.getRightOperand(); final IElementType opType = expression.getOperationTokenType(); if (ControlFlowBuilderUtil.isInstanceOfBinary(expression)) { expression.getLeftOperand().accept(this); processInstanceOf(expression); return; } if (opType != mLOR && opType != mLAND && opType != kIN) { left.accept(this); if (right != null) { right.accept(this); } visitCall(expression); return; } ConditionInstruction condition = new ConditionInstruction(expression); addNodeAndCheckPending(condition); registerCondition(condition); left.accept(this); if (right == null) return; final List<GotoInstruction> negations = collectAndRemoveAllPendingNegations(expression); visitCall(expression); if (opType == mLAND) { InstructionImpl head = myHead; if (negations.isEmpty()) { addNode(new NegatingGotoInstruction(expression, condition)); handlePossibleReturn(expression); addPendingEdge(expression, myHead); } else { for (GotoInstruction negation : negations) { myHead = negation; handlePossibleReturn(expression); addPendingEdge(expression, myHead); } } myHead = head; } else /*if (opType == mLOR)*/ { final InstructionImpl instruction = addNodeAndCheckPending( new InstructionImpl(expression)); // collect all pending edges from left argument handlePossibleReturn(expression); addPendingEdge(expression, myHead); myHead = instruction; InstructionImpl head = reduceAllNegationsIntoInstruction(expression, negations); if (head != null) myHead = head; // addNode(new NegatingGotoInstruction(expression, myInstructionNumber++, condition)); } myConditions.removeFirstOccurrence(condition); right.accept(this); }
@Override public void visitParenthesizedExpression(GrParenthesizedExpression expression) { final GrExpression operand = expression.getOperand(); if (operand != null) operand.accept(this); }