public void visitReferenceExpression(GrReferenceExpression refExpr) {
    super.visitReferenceExpression(refExpr);

    if (myPolicy.isReferenceAccepted(refExpr)) {
      String name = refExpr.getReferenceName();
      if (name == null) return;

      if (ControlFlowUtils.isIncOrDecOperand(refExpr)) {
        final InstructionImpl i = new ReadWriteVariableInstruction(name, refExpr, READ);
        addNodeAndCheckPending(i);
        addNode(new ReadWriteVariableInstruction(name, refExpr, WRITE));
      } else {
        final int type = PsiUtil.isLValue(refExpr) ? WRITE : READ;
        addNodeAndCheckPending(new ReadWriteVariableInstruction(name, refExpr, type));
        if (refExpr.getParent() instanceof GrArgumentList
            && refExpr.getParent().getParent() instanceof GrCall) {
          addNodeAndCheckPending(new ArgumentInstruction(refExpr));
        }
      }
    }

    if (refExpr.isQualified() && !(refExpr.getParent() instanceof GrCall)) {
      visitCall(refExpr);
    }
  }
  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));
  }
  public void visitTypeDefinition(final GrTypeDefinition typeDefinition) {
    if (!(typeDefinition instanceof GrAnonymousClassDefinition)) return;

    final Set<ReadWriteVariableInstruction> vars =
        collectUsedVariableWithoutInitialization(typeDefinition);

    for (ReadWriteVariableInstruction var : vars) {
      PsiElement element = var.getElement();
      if (!(element instanceof GrReferenceExpression)
          || myPolicy.isReferenceAccepted((GrReferenceExpression) element)) {
        addNodeAndCheckPending(
            new ReadWriteVariableInstruction(var.getVariableName(), typeDefinition, READ));
      }
    }
    addNodeAndCheckPending(new InstructionImpl(typeDefinition));
  }
  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);
    }
  }