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)};
       }
     }
   }
 }
 public void visitIfStatement(GrIfStatement ifStatement) {
   if (myExpression.equals(ifStatement.getCondition())) {
     myResult =
         new TypeConstraint[] {
           new SubtypeConstraint(TypesUtil.getJavaLangObject(ifStatement), PsiType.BOOLEAN)
         };
   } else if (myExpression.equals(ifStatement.getThenBranch())
       || myExpression.equals(ifStatement.getElseBranch())) {
     checkExitPoint();
   }
 }
 @Override
 public void visitOpenBlock(GrOpenBlock block) {
   final GrStatement[] statements = block.getStatements();
   if (statements.length > 0 && myExpression.equals(statements[statements.length - 1])) {
     checkExitPoint();
   }
 }
 public void visitTraditionalForClause(GrTraditionalForClause forClause) {
   if (myExpression.equals(forClause.getCondition())) {
     myResult =
         new TypeConstraint[] {
           new SubtypeConstraint(TypesUtil.getJavaLangObject(forClause), PsiType.BOOLEAN)
         };
   }
 }
 public void visitWhileStatement(GrWhileStatement whileStatement) {
   if (myExpression.equals(whileStatement.getCondition())) {
     myResult =
         new TypeConstraint[] {
           new SubtypeConstraint(TypesUtil.getJavaLangObject(whileStatement), PsiType.BOOLEAN)
         };
   }
 }
    @Override
    public void visitAnnotationNameValuePair(GrAnnotationNameValuePair nameValuePair) {
      if (myExpression.equals(nameValuePair.getValue())) {
        final PsiClass annot = ResolveUtil.resolveAnnotation(nameValuePair.getParent());
        if (annot != null) {
          final String name = nameValuePair.getName();
          if (name != null) {
            final PsiMethod[] attrs = annot.findMethodsByName(name, false);
            if (attrs.length > 0) {
              PsiType type = attrs[0].getReturnType();
              while (type instanceof PsiArrayType) type = ((PsiArrayType) type).getComponentType();
              if (type != null && isAcceptableAnnotationValueType(type)) {
                myResult = createSimpleSubTypeResult(type);
              }
            }
          } else {
            final PsiMethod[] valueAttr = annot.findMethodsByName("value", false);
            boolean canHaveSimpleExpr = valueAttr.length > 0;
            final PsiMethod[] methods = annot.getMethods();
            for (PsiMethod method : methods) {
              if (!("value".equals(method.getName())
                  || method instanceof PsiAnnotationMethod
                      && ((PsiAnnotationMethod) method).getDefaultValue() != null)) {
                canHaveSimpleExpr = false;
              }
            }

            if (canHaveSimpleExpr) {
              PsiType type = valueAttr[0].getReturnType();
              while (type instanceof PsiArrayType) type = ((PsiArrayType) type).getComponentType();
              if (type != null && isAcceptableAnnotationValueType(type)) {
                myResult = createSimpleSubTypeResult(type);
              }
            }
          }
        }
      }
    }
    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()]);
        }
      }
    }
 public void visitVariable(GrVariable variable) {
   if (myExpression.equals(variable.getInitializerGroovy())) {
     PsiType type = variable.getType();
     myResult = createSimpleSubTypeResult(type);
   }
 }