public void replaceDotToken(PsiElement newDot) {
    if (newDot == null) return;
    if (!TokenSets.DOTS.contains(newDot.getNode().getElementType())) return;
    final PsiElement oldDot = getDotToken();
    if (oldDot == null) return;

    getNode().replaceChild(oldDot.getNode(), newDot.getNode());
  }
    private static PsiType doFun(GrReferenceExpression refExpr) {
      if (ResolveUtil.isClassReference(refExpr)) {
        GrExpression qualifier = refExpr.getQualifier();
        LOG.assertTrue(qualifier != null);
        return TypesUtil.createJavaLangClassType(
            qualifier.getType(), refExpr.getProject(), refExpr.getResolveScope());
      }

      if (PsiUtil.isCompileStatic(refExpr)) {
        final GroovyResolveResult resolveResult = refExpr.advancedResolve();
        final PsiElement resolvedF = resolveResult.getElement();
        final PsiType type;
        if (resolvedF instanceof GrField) {
          type = ((GrField) resolvedF).getType();
        } else if (resolvedF instanceof GrAccessorMethod) {
          type = ((GrAccessorMethod) resolvedF).getProperty().getType();
        } else {
          type = null;
        }
        if (type != null) {
          return resolveResult.getSubstitutor().substitute(type);
        }
      }

      final PsiElement resolved = refExpr.resolve();
      final PsiType nominal = refExpr.getNominalType();

      Boolean reassigned = GrReassignedLocalVarsChecker.isReassignedVar(refExpr);
      if (reassigned != null && reassigned.booleanValue()) {
        return GrReassignedLocalVarsChecker.getReassignedVarType(refExpr, true);
      }

      final PsiType inferred = getInferredTypes(refExpr, resolved);
      if (inferred == null) {
        if (nominal == null) {
          // inside nested closure we could still try to infer from variable initializer. Not sound,
          // but makes sense
          if (resolved instanceof GrVariable) {
            LOG.assertTrue(resolved.isValid());
            return ((GrVariable) resolved).getTypeGroovy();
          }
        }

        return nominal;
      }

      if (nominal == null) return inferred;
      if (!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(nominal), inferred, false)) {
        if (resolved instanceof GrVariable
            && ((GrVariable) resolved).getTypeElementGroovy() != null) {
          return nominal;
        }
      }
      return inferred;
    }
  @NotNull
  public static PsiType createSetType(@NotNull PsiElement context, @NotNull PsiType type) {
    JavaPsiFacade facade = JavaPsiFacade.getInstance(context.getProject());
    GlobalSearchScope resolveScope = context.getResolveScope();

    PsiClass setClass = facade.findClass(JAVA_UTIL_SET, resolveScope);
    if (setClass != null && setClass.getTypeParameters().length == 1) {
      return facade.getElementFactory().createType(setClass, type);
    }

    return facade.getElementFactory().createTypeByFQClassName(JAVA_UTIL_SET, resolveScope);
  }
  public PsiElement handleElementRenameSimple(String newElementName)
      throws IncorrectOperationException {
    if (!PsiUtil.isValidReferenceName(newElementName)) {
      final PsiElement old = getReferenceNameElement();
      if (old == null) throw new IncorrectOperationException("ref has no name element");

      PsiElement element =
          GroovyPsiElementFactory.getInstance(getProject())
              .createStringLiteralForReference(newElementName);
      old.replace(element);
      return this;
    }

    return super.handleElementRenameSimple(newElementName);
  }
  public String getReferenceName() {
    PsiElement nameElement = getReferenceNameElement();
    if (nameElement != null) {
      IElementType nodeType = nameElement.getNode().getElementType();
      if (TokenSets.STRING_LITERAL_SET.contains(nodeType)) {
        final Object value = GrLiteralImpl.getLiteralValue(nameElement);
        if (value instanceof String) {
          return (String) value;
        }
      }

      return nameElement.getText();
    }
    return null;
  }
  public static boolean isAssignableWithoutConversions(
      @Nullable PsiType lType, @Nullable PsiType rType, @NotNull PsiElement context) {
    if (lType == null || rType == null) return false;

    if (rType == PsiType.NULL) {
      return !(lType instanceof PsiPrimitiveType);
    }

    PsiManager manager = context.getManager();
    GlobalSearchScope scope = context.getResolveScope();

    if (rType instanceof GrTupleType && ((GrTupleType) rType).getComponentTypes().length == 0) {
      if (lType instanceof PsiArrayType
          || InheritanceUtil.isInheritor(lType, JAVA_UTIL_LIST)
          || InheritanceUtil.isInheritor(lType, JAVA_UTIL_SET)) {
        return true;
      }
    }

    if (isClassType(rType, GROOVY_LANG_GSTRING) && lType.equalsToText(JAVA_LANG_STRING)) {
      return true;
    }

    if (isNumericType(lType) && isNumericType(rType)) {
      lType = unboxPrimitiveTypeWrapper(lType);
      if (isClassType(lType, JAVA_MATH_BIG_DECIMAL)) lType = PsiType.DOUBLE;
      rType = unboxPrimitiveTypeWrapper(rType);
      if (isClassType(rType, JAVA_MATH_BIG_DECIMAL)) rType = PsiType.DOUBLE;
    } else {
      rType = boxPrimitiveType(rType, manager, scope);
      lType = boxPrimitiveType(lType, manager, scope);
    }

    if (rType instanceof GrMapType || rType instanceof GrTupleType) {
      Boolean result = isAssignableForNativeTypes(lType, (PsiClassType) rType, context);
      if (result != null && result.booleanValue()) return true;
    }

    if (TypeConversionUtil.isAssignable(lType, rType)) {
      return true;
    }

    return false;
  }
  private void processMethods(final MethodResolverProcessor methodResolver) {
    GrReferenceResolveUtil.resolveImpl(methodResolver, this);
    if (methodResolver.hasApplicableCandidates()) {
      return;
    }

    // Search in ClosureMissingMethodContributor
    if (!isQualified() && getContext() instanceof GrMethodCall) {
      for (PsiElement e = this.getContext(); e != null; e = e.getContext()) {
        if (e instanceof GrClosableBlock) {
          ResolveState state = ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, e);
          for (ClosureMissingMethodContributor contributor :
              ClosureMissingMethodContributor.EP_NAME.getExtensions()) {
            if (!contributor.processMembers((GrClosableBlock) e, methodResolver, this, state)) {
              return;
            }
          }
        }
      }
    }
  }
    @Nullable
    public PsiType fun(GrReferenceExpressionImpl refExpr) {
      PsiType result = GrReassignedLocalVarsChecker.checkReassignedVar(refExpr, true);
      if (result != null) return result;

      if (GrUnresolvedAccessInspection.isClassReference(refExpr)) {
        GrExpression qualifier = refExpr.getQualifier();
        LOG.assertTrue(qualifier != null);
        return TypesUtil.createJavaLangClassType(
            qualifier.getType(), refExpr.getProject(), refExpr.getResolveScope());
      }

      final PsiElement resolved = refExpr.resolve();
      final PsiType inferred = getInferredTypes(refExpr, resolved);
      final PsiType nominal = refExpr.getNominalType();
      if (inferred == null || PsiType.NULL.equals(inferred)) {
        if (nominal == null) {
          // inside nested closure we could still try to infer from variable initializer. Not sound,
          // but makes sense
          if (resolved instanceof GrVariable) {
            LOG.assertTrue(resolved.isValid());
            return ((GrVariable) resolved).getTypeGroovy();
          }
        }

        return nominal;
      }

      if (nominal == null) return inferred;
      if (!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(nominal), inferred, false)) {
        if (resolved instanceof GrVariable
            && ((GrVariable) resolved).getTypeElementGroovy() != null) {
          return nominal;
        }
      }
      return inferred;
    }
 @Nullable
 public IElementType getDotTokenType() {
   PsiElement dot = getDotToken();
   return dot == null ? null : dot.getNode().getElementType();
 }
  @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;
  }
 private static void assertAllAreValid(GroovyResolveResult[] candidates) {
   for (GroovyResolveResult candidate : candidates) {
     final PsiElement element = candidate.getElement();
     LOG.assertTrue(element == null || element.isValid());
   }
 }
  private GroovyResolveResult[] resolveTypeOrPropertyInner() {
    PsiElement nameElement = getReferenceNameElement();
    String name = getReferenceName();

    if (name == null || nameElement == null) return GroovyResolveResult.EMPTY_ARRAY;

    IElementType nameType = nameElement.getNode().getElementType();
    if (nameType == GroovyTokenTypes.kTHIS) {
      ArrayList<GroovyResolveResult> results = new ArrayList<GroovyResolveResult>();
      if (GrReferenceResolveUtil.resolveThisExpression(this, results)) {
        return results.toArray(new GroovyResolveResult[results.size()]);
      }
    } else if (nameType == GroovyTokenTypes.kSUPER) {
      ArrayList<GroovyResolveResult> results = new ArrayList<GroovyResolveResult>();
      if (GrReferenceResolveUtil.resolveSuperExpression(this, results)) {
        return results.toArray(new GroovyResolveResult[results.size()]);
      }
    }

    EnumSet<ClassHint.ResolveKind> kinds =
        getParent() instanceof GrReferenceExpression
            ? ResolverProcessor.RESOLVE_KINDS_CLASS_PACKAGE
            : ResolverProcessor.RESOLVE_KINDS_CLASS;

    GroovyResolveResult[] classCandidates = null;

    ResolverProcessor processor = new PropertyResolverProcessor(name, this);
    GrReferenceResolveUtil.resolveImpl(processor, this);
    final GroovyResolveResult[] fieldCandidates = processor.getCandidates();

    if (hasAt()) {
      return fieldCandidates;
    }

    boolean canBeClassOrPackage = ResolveUtil.canBeClassOrPackage(this);

    if (canBeClassOrPackage && findClassOrPackageAtFirst()) {
      boolean preferVar = containsLocalVar(fieldCandidates);
      if (!preferVar) {
        ResolverProcessor classProcessor = new ClassResolverProcessor(name, this, kinds);
        GrReferenceResolveUtil.resolveImpl(classProcessor, this);
        classCandidates = classProcessor.getCandidates();
        if (classCandidates.length > 0) return classCandidates;
      }
    }

    // if reference expression is in class we need to return field instead of accessor method
    for (GroovyResolveResult candidate : fieldCandidates) {
      final PsiElement element = candidate.getElement();
      if (element instanceof PsiField) {
        final PsiClass containingClass = ((PsiField) element).getContainingClass();
        if (containingClass != null && PsiTreeUtil.isContextAncestor(containingClass, this, true))
          return fieldCandidates;
      } else {
        return fieldCandidates;
      }
    }

    final boolean isLValue = PsiUtil.isLValue(this);
    String[] accessorNames =
        isLValue
            ? GroovyPropertyUtils.suggestSettersName(name)
            : GroovyPropertyUtils.suggestGettersName(name);
    List<GroovyResolveResult> accessorResults = new ArrayList<GroovyResolveResult>();
    for (String accessorName : accessorNames) {
      AccessorResolverProcessor accessorResolver =
          new AccessorResolverProcessor(
              accessorName,
              name,
              this,
              !isLValue,
              false,
              GrReferenceResolveUtil.getQualifierType(this),
              getTypeArguments());
      GrReferenceResolveUtil.resolveImpl(accessorResolver, this);
      final GroovyResolveResult[] candidates = accessorResolver.getCandidates();

      // can be only one correct candidate or some incorrect
      if (candidates.length == 1 && candidates[0].isStaticsOK() && candidates[0].isAccessible()) {
        return candidates;
      } else {
        ContainerUtil.addAll(accessorResults, candidates);
      }
    }
    if (fieldCandidates.length > 0) return fieldCandidates;
    if (classCandidates == null && canBeClassOrPackage) {
      ResolverProcessor classProcessor = new ClassResolverProcessor(name, this, kinds);
      GrReferenceResolveUtil.resolveImpl(classProcessor, this);
      classCandidates = classProcessor.getCandidates();
    }
    if (classCandidates != null && classCandidates.length > 0) return classCandidates;
    if (accessorResults.size() > 0) return new GroovyResolveResult[] {accessorResults.get(0)};
    return GroovyResolveResult.EMPTY_ARRAY;
  }
 @NotNull
 public static PsiClassType createTypeByFQClassName(
     @NotNull String fqName, @NotNull PsiElement context) {
   return GroovyPsiManager.getInstance(context.getProject())
       .createTypeByFQClassName(fqName, context.getResolveScope());
 }
 @NotNull
 public static PsiClassType getJavaLangObject(@NotNull PsiElement context) {
   return PsiType.getJavaLangObject(context.getManager(), context.getResolveScope());
 }
  public static boolean isAssignable(
      @Nullable PsiType lType, @Nullable PsiType rType, @NotNull PsiElement context) {
    if (lType == null || rType == null) {
      return false;
    }

    if (rType instanceof PsiIntersectionType) {
      for (PsiType child : ((PsiIntersectionType) rType).getConjuncts()) {
        if (isAssignable(lType, child, context)) {
          return true;
        }
      }
      return false;
    }
    if (lType instanceof PsiIntersectionType) {
      for (PsiType child : ((PsiIntersectionType) lType).getConjuncts()) {
        if (!isAssignable(child, rType, context)) {
          return false;
        }
      }
      return true;
    }

    if (rType == PsiType.NULL) {
      return !(lType instanceof PsiPrimitiveType);
    }

    if (isNumericType(lType) && isNumericType(rType)) {
      return true;
    }

    if (isClassType(lType, JAVA_LANG_STRING)) {
      return true;
    }

    final PsiManager manager = context.getManager();
    final GlobalSearchScope scope = context.getResolveScope();

    if (lType instanceof PsiArrayType) {
      PsiType lComponentType = ((PsiArrayType) lType).getComponentType();
      PsiType rComponentType = ClosureParameterEnhancer.findTypeForIteration(rType, context);
      if (rComponentType != null && isAssignable(lComponentType, rComponentType, context)) {
        return true;
      }
    }

    if (unboxPrimitiveTypeWrapper(lType) == PsiType.CHAR
        && (isClassType(rType, JAVA_LANG_STRING) || isClassType(rType, GROOVY_LANG_GSTRING))) {
      return true;
    }

    if (isAssignableByMethodCallConversion(lType, rType, context)) return true;

    lType = boxPrimitiveType(lType, manager, scope);
    rType = boxPrimitiveType(rType, manager, scope);
    if (lType.isAssignableFrom(rType)) {
      return true;
    }

    if (context instanceof GroovyPsiElement) {
      for (GrTypeConverter converter : GrTypeConverter.EP_NAME.getExtensions()) {
        if (!converter.isAllowedInMethodCall()) {
          Boolean result = converter.isConvertible(lType, rType, (GroovyPsiElement) context);
          if (result != null) {
            return result;
          }
        }
      }
    }

    return false;
  }
  @NotNull
  private GroovyResolveResult[] resolveTypeOrPropertyInner() {
    PsiElement nameElement = getReferenceNameElement();
    String name = getReferenceName();

    if (name == null || nameElement == null) return GroovyResolveResult.EMPTY_ARRAY;

    IElementType nameType = nameElement.getNode().getElementType();
    if (nameType == GroovyTokenTypes.kTHIS) {
      GroovyResolveResult[] results = GrThisReferenceResolver.resolveThisExpression(this);
      if (results != null) {
        return results;
      }
    } else if (nameType == GroovyTokenTypes.kSUPER) {
      GroovyResolveResult[] results = GrSuperReferenceResolver.resolveSuperExpression(this);
      if (results != null) {
        return results;
      }
    }

    EnumSet<ClassHint.ResolveKind> kinds =
        getParent() instanceof GrReferenceExpression
            ? ClassHint.RESOLVE_KINDS_CLASS_PACKAGE
            : ClassHint.RESOLVE_KINDS_CLASS;

    GroovyResolveResult[] classCandidates = null;

    GrReferenceResolveRunner resolveRunner = new GrReferenceResolveRunner(this);

    ResolverProcessor processor = new PropertyResolverProcessor(name, this);
    resolveRunner.resolveImpl(processor);
    final GroovyResolveResult[] fieldCandidates = processor.getCandidates();

    if (hasAt()) {
      return fieldCandidates;
    }

    boolean canBeClassOrPackage = ResolveUtil.canBeClassOrPackage(this);

    if (canBeClassOrPackage && findClassOrPackageAtFirst()) {
      ResolverProcessor classProcessor = new ClassResolverProcessor(name, this, kinds);
      resolveRunner.resolveImpl(classProcessor);
      classCandidates = classProcessor.getCandidates();
      if (classCandidates.length > 0 && containsPackage(classCandidates)) {
        final PsiElement firstNonReferenceExprParent =
            PsiTreeUtil.skipParentsOfType(this, GrReferenceExpressionImpl.class);
        final GrReferenceExpressionImpl topRef =
            (GrReferenceExpressionImpl)
                PsiTreeUtil.findFirstParent(
                    this,
                    new Condition<PsiElement>() {
                      @Override
                      public boolean value(PsiElement parent) {
                        return parent.getParent() == firstNonReferenceExprParent
                            && parent instanceof GrReferenceExpressionImpl;
                      }
                    });
        if (topRef != null) {
          final String fqn = topRef.getTextSkipWhiteSpaceAndComments();
          if (JavaPsiFacade.getInstance(getProject()).findClass(fqn, getResolveScope()) != null) {
            return classCandidates;
          }
        }
      }
    }

    // if reference expression is in class we need to return field instead of accessor method
    for (GroovyResolveResult candidate : fieldCandidates) {
      final PsiElement element = candidate.getElement();
      if (element instanceof PsiField) {
        final PsiClass containingClass = ((PsiField) element).getContainingClass();
        if (containingClass != null && PsiUtil.getContextClass(this) == containingClass)
          return fieldCandidates;
      } else if (!(element instanceof GrBindingVariable)) {
        return fieldCandidates;
      }
    }

    if (classCandidates != null && classCandidates.length > 0) return classCandidates;

    final boolean isLValue = PsiUtil.isLValue(this);
    String[] accessorNames =
        isLValue
            ? GroovyPropertyUtils.suggestSettersName(name)
            : GroovyPropertyUtils.suggestGettersName(name);
    List<GroovyResolveResult> accessorResults = new ArrayList<GroovyResolveResult>();
    for (String accessorName : accessorNames) {
      AccessorResolverProcessor accessorResolver =
          new AccessorResolverProcessor(
              accessorName,
              name,
              this,
              !isLValue,
              false,
              PsiImplUtil.getQualifierType(this),
              getTypeArguments());
      resolveRunner.resolveImpl(accessorResolver);
      final GroovyResolveResult[] candidates = accessorResolver.getCandidates();

      // can be only one correct candidate or some incorrect
      if (candidates.length == 1 && candidates[0].isStaticsOK() && candidates[0].isAccessible()) {
        return candidates;
      } else {
        ContainerUtil.addAll(accessorResults, candidates);
      }
    }

    final ArrayList<GroovyResolveResult> fieldList = ContainerUtil.newArrayList(fieldCandidates);
    filterOutBindings(fieldList);
    if (!fieldList.isEmpty()) {
      return fieldList.toArray(new GroovyResolveResult[fieldList.size()]);
    }

    if (classCandidates == null && canBeClassOrPackage) {
      ResolverProcessor classProcessor = new ClassResolverProcessor(name, this, kinds);
      resolveRunner.resolveImpl(classProcessor);
      classCandidates = classProcessor.getCandidates();
    }

    if (classCandidates != null && classCandidates.length > 0) return classCandidates;
    if (!accessorResults.isEmpty()) return new GroovyResolveResult[] {accessorResults.get(0)};
    return GroovyResolveResult.EMPTY_ARRAY;
  }