private static boolean assignmentExpressionsAreEquivalent(
     @NotNull GrAssignmentExpression assignExp1, @NotNull GrAssignmentExpression assignExp2) {
   final IElementType sign1 = assignExp1.getOperationToken();
   final IElementType sign2 = assignExp2.getOperationToken();
   if (!sign1.equals(sign2)) {
     return false;
   }
   final GrExpression lhs1 = assignExp1.getLValue();
   final GrExpression lhs2 = assignExp2.getLValue();
   final GrExpression rhs1 = assignExp1.getRValue();
   final GrExpression rhs2 = assignExp2.getRValue();
   return expressionsAreEquivalent(lhs1, lhs2) && expressionsAreEquivalent(rhs1, rhs2);
 }
 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)};
       }
     }
   }
 }
  @Nullable
  private static GrAssignmentExpression genRefForSetter(GrMethodCall call, String accessorName) {
    String name = GroovyPropertyUtils.getPropertyNameBySetterName(accessorName);
    if (name == null) return null;
    GrExpression value = call.getExpressionArguments()[0];
    GrReferenceExpression refExpr = (GrReferenceExpression) call.getInvokedExpression();

    final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(call.getProject());
    final GrAssignmentExpression assignment =
        (GrAssignmentExpression) factory.createStatementFromText("yyy = xxx", call);

    GrReferenceExpression lvalueRef = (GrReferenceExpression) assignment.getLValue();
    lvalueRef.setQualifier(refExpr.getQualifier());
    lvalueRef.handleElementRenameSimple(name);
    assignment.getRValue().replaceWithExpression(value, true);

    return assignment;
  }
  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);
    }
  }
  @Nullable
  private PsiType getNominalTypeInner(PsiElement resolved) {
    if (resolved == null && !"class".equals(getReferenceName())) {
      resolved = resolve();
    }

    if (resolved instanceof PsiClass) {
      final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
      if (PsiUtil.isInstanceThisRef(this)) {
        final PsiClassType categoryType = GdkMethodUtil.getCategoryType((PsiClass) resolved);
        if (categoryType != null) {
          return categoryType;
        } else {
          return factory.createType((PsiClass) resolved);
        }
      }
      if (getParent() instanceof GrReferenceExpression || PsiUtil.isSuperReference(this)) {
        return factory.createType((PsiClass) resolved);
      } else {
        return TypesUtil.createJavaLangClassType(
            factory.createType((PsiClass) resolved), getProject(), getResolveScope());
      }
    }

    if (resolved instanceof GrVariable) {
      return ((GrVariable) resolved).getDeclaredType();
    }

    if (resolved instanceof PsiVariable) {
      return ((PsiVariable) resolved).getType();
    }

    if (resolved instanceof PsiMethod) {
      PsiMethod method = (PsiMethod) resolved;
      if (PropertyUtil.isSimplePropertySetter(method)
          && !method.getName().equals(getReferenceName())) {
        return method.getParameterList().getParameters()[0].getType();
      }

      // 'class' property with explicit generic
      PsiClass containingClass = method.getContainingClass();
      if (containingClass != null
          && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName())
          && "getClass".equals(method.getName())) {
        return TypesUtil.createJavaLangClassType(
            GrReferenceResolveUtil.getQualifierType(this), getProject(), getResolveScope());
      }

      return PsiUtil.getSmartReturnType(method);
    }

    if (resolved instanceof GrReferenceExpression) {
      PsiElement parent = resolved.getParent();
      if (parent instanceof GrAssignmentExpression) {
        GrAssignmentExpression assignment = (GrAssignmentExpression) parent;
        if (resolved.equals(assignment.getLValue())) {
          GrExpression rValue = assignment.getRValue();
          if (rValue != null) {
            PsiType rType = rValue.getType();
            if (rType != null) {
              return rType;
            }
          }
        }
      }
    }

    if (resolved == null) {
      final PsiType fromClassRef = getTypeFromClassRef(this);
      if (fromClassRef != null) {
        return fromClassRef;
      }

      final PsiType fromMapAccess = getTypeFromMapAccess(this);
      if (fromMapAccess != null) {
        return fromMapAccess;
      }

      final PsiType fromSpreadOperator = getTypeFromSpreadOperator(this);
      if (fromSpreadOperator != null) {
        return fromSpreadOperator;
      }
    }

    return null;
  }