public void visitAssignmentExpression(GrAssignmentExpression expression) {
   GrExpression rValue = expression.getRValue();
   GrExpression lValue = expression.getLValue();
   if (myExpression.equals(rValue)) {
     PsiType lType = lValue.getNominalType();
     if (lType != null) {
       myResult = new TypeConstraint[] {SubtypeConstraint.create(lType)};
     } else if (lValue instanceof GrReferenceExpression) {
       GroovyResolveResult result = ((GrReferenceExpression) lValue).advancedResolve();
       PsiElement resolved = result.getElement();
       if (resolved instanceof GrVariable) {
         PsiType type = ((GrVariable) resolved).getTypeGroovy();
         if (type != null) {
           myResult =
               new TypeConstraint[] {
                 SubtypeConstraint.create(result.getSubstitutor().substitute(type))
               };
         }
       }
     }
   } else if (myExpression.equals(lValue)) {
     if (rValue != null) {
       PsiType rType = rValue.getType();
       if (rType != null) {
         myResult = new TypeConstraint[] {SupertypeConstraint.create(rType)};
       }
     }
   }
 }
 @Override
 public void visitListOrMap(GrListOrMap listOrMap) {
   if (listOrMap.isMap()) return;
   final TypeConstraint[] constraints = calculateTypeConstraints(listOrMap);
   List<PsiType> result = new ArrayList<PsiType>(constraints.length);
   for (TypeConstraint constraint : constraints) {
     if (constraint instanceof SubtypeConstraint) {
       final PsiType type = constraint.getType();
       final PsiType iterable =
           com.intellij.psi.util.PsiUtil.extractIterableTypeParameter(type, true);
       if (iterable != null) {
         result.add(iterable);
       }
     }
   }
   if (result.size() == 0) {
     myResult = TypeConstraint.EMPTY_ARRAY;
   } else {
     myResult = new TypeConstraint[result.size()];
     for (int i = 0; i < result.size(); i++) {
       final PsiType type = result.get(i);
       if (type != null) {
         myResult[i] = SubtypeConstraint.create(type);
       }
     }
   }
 }
    private void addConstraintsFromMap(
        List<TypeConstraint> constraints, Map<GrExpression, Pair<PsiParameter, PsiType>> map) {
      if (map == null) return;

      final Pair<PsiParameter, PsiType> pair = map.get(myExpression);
      if (pair == null) return;

      final PsiType type = pair.second;
      if (type == null) return;

      constraints.add(SubtypeConstraint.create(type));

      if (type instanceof PsiArrayType && pair.first.isVarArgs()) {
        constraints.add(SubtypeConstraint.create(((PsiArrayType) type).getComponentType()));
      }
    }
 public void visitReturnStatement(GrReturnStatement returnStatement) {
   GrParametersOwner parent =
       PsiTreeUtil.getParentOfType(returnStatement, GrMethod.class, GrClosableBlock.class);
   if (parent instanceof GrMethod) {
     GrTypeElement typeElement = ((GrMethod) parent).getReturnTypeElementGroovy();
     if (typeElement != null) {
       PsiType type = typeElement.getType();
       myResult = new TypeConstraint[] {SubtypeConstraint.create(type)};
     }
   }
 }
    @Override
    public void visitCaseLabel(GrCaseLabel caseLabel) {
      final PsiElement parent = caseLabel.getParent().getParent();
      assert parent instanceof GrSwitchStatement : parent + " of class " + parent.getClass();
      final GrExpression condition = ((GrSwitchStatement) parent).getCondition();
      if (condition == null) return;

      final PsiType type = condition.getType();
      if (type == null) return;

      myResult = new TypeConstraint[] {SubtypeConstraint.create(type)};
    }
    @Override
    public void visitSwitchStatement(GrSwitchStatement switchStatement) {
      final GrCaseSection[] sections = switchStatement.getCaseSections();
      List<PsiType> types = new ArrayList<PsiType>(sections.length);
      for (GrCaseSection section : sections) {
        final GrExpression value = section.getCaseLabel().getValue();
        final PsiType type = value != null ? value.getType() : null;
        if (type != null) types.add(type);
      }

      final PsiType upperBoundNullable =
          TypesUtil.getLeastUpperBoundNullable(types, switchStatement.getManager());
      if (upperBoundNullable == null) return;

      myResult = new TypeConstraint[] {SubtypeConstraint.create(upperBoundNullable)};
    }
    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 visitThrowStatement(GrThrowStatement throwStatement) {
   final PsiClassType throwable =
       PsiType.getJavaLangThrowable(myExpression.getManager(), throwStatement.getResolveScope());
   myResult = new TypeConstraint[] {SubtypeConstraint.create(throwable)};
 }