@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); } }
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); }
public void visitArgumentList(GrArgumentList list) { List<TypeConstraint> constraints = new ArrayList<TypeConstraint>(); for (GroovyResolveResult variant : ResolveUtil.getCallVariants(list)) { final Map<GrExpression, Pair<PsiParameter, PsiType>> map = GrClosureSignatureUtil.mapArgumentsToParameters( variant, list, true, true, list.getNamedArguments(), list.getExpressionArguments(), GrClosableBlock.EMPTY_ARRAY); addConstraintsFromMap(constraints, map); } if (!constraints.isEmpty()) { myResult = constraints.toArray(new TypeConstraint[constraints.size()]); } }
public void visitMethodCallExpression(GrMethodCallExpression methodCall) { final GrExpression invokedExpression = methodCall.getInvokedExpression(); if (myExpression.equals(invokedExpression)) { myResult = new TypeConstraint[] { SubtypeConstraint.create(GroovyCommonClassNames.GROOVY_LANG_CLOSURE, methodCall) }; return; } final GrClosableBlock[] closureArgs = methodCall.getClosureArguments(); //noinspection SuspiciousMethodCalls final int closureIndex = Arrays.asList(closureArgs).indexOf(myExpression); if (closureIndex >= 0) { List<TypeConstraint> constraints = new ArrayList<TypeConstraint>(); for (GroovyResolveResult variant : ResolveUtil.getCallVariants(myExpression)) { final GrArgumentList argumentList = methodCall.getArgumentList(); final GrNamedArgument[] namedArgs = argumentList == null ? GrNamedArgument.EMPTY_ARRAY : argumentList.getNamedArguments(); final GrExpression[] expressionArgs = argumentList == null ? GrExpression.EMPTY_ARRAY : argumentList.getExpressionArguments(); try { final Map<GrExpression, Pair<PsiParameter, PsiType>> map = GrClosureSignatureUtil.mapArgumentsToParameters( variant, methodCall, true, true, namedArgs, expressionArgs, closureArgs); addConstraintsFromMap(constraints, map); } catch (RuntimeException e) { LOG.error( "call: " + methodCall.getText() + "\nsymbol: " + variant.getElement().getText(), e); } } if (!constraints.isEmpty()) { myResult = constraints.toArray(new TypeConstraint[constraints.size()]); } } }
@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); }