public void visitClosure(GrClosableBlock closure) { // do not go inside closures except gstring injections if (closure.getParent() instanceof GrStringInjection) { for (GrParameter parameter : closure.getAllParameters()) { if (myPolicy.isVariableInitialized(parameter)) { addNode(new ReadWriteVariableInstruction(parameter.getName(), parameter, WRITE)); } } addNode(new ReadWriteVariableInstruction("owner", closure.getLBrace(), WRITE)); super.visitClosure(closure); return; } ReadWriteVariableInstruction[] reads = ControlFlowBuilderUtil.getReadsWithoutPriorWrites(closure.getControlFlow(), false); for (ReadWriteVariableInstruction read : reads) { PsiElement element = read.getElement(); if (!(element instanceof GrReferenceExpression) || myPolicy.isReferenceAccepted((GrReferenceExpression) element)) { addNodeAndCheckPending( new ReadWriteVariableInstruction(read.getVariableName(), closure, READ)); } } addNodeAndCheckPending(new InstructionImpl(closure)); }
@Nullable private static PsiType getTypeByRef(@NotNull GrReferenceExpression invoked) { final GroovyResolveResult[] results = ControlFlowBuilderUtil.resolveNonQualifiedRefWithoutFlow(invoked); if (results.length == 1) { final PsiElement element = results[0].getElement(); if (element instanceof PsiVariable) { return ((PsiVariable) element).getType(); } } return null; }
@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); }
private void handlePossibleReturn(@NotNull GrStatement possibleReturn) { if (possibleReturn instanceof GrExpression && ControlFlowBuilderUtil.isCertainlyReturnStatement(possibleReturn)) { addNodeAndCheckPending(new MaybeReturnInstruction((GrExpression) possibleReturn)); } }