@Nullable
  private static HighlightInfo checkRefInner(GrReferenceExpression ref) {
    PsiElement refNameElement = ref.getReferenceNameElement();
    if (refNameElement == null) return null;

    boolean cannotBeDynamic = PsiUtil.isCompileStatic(ref) || isPropertyAccessInStaticMethod(ref);
    GroovyResolveResult resolveResult = getBestResolveResult(ref);

    if (resolveResult.getElement() != null) {
      if (!isInspectionEnabled(ref.getContainingFile(), ref.getProject())) return null;

      if (isStaticOk(resolveResult)) return null;
      String message = GroovyBundle.message("cannot.reference.non.static", ref.getReferenceName());
      return createAnnotationForRef(ref, cannotBeDynamic, message);
    }

    if (ResolveUtil.isKeyOfMap(ref) || isClassReference(ref)) {
      return null;
    }

    if (!cannotBeDynamic) {
      if (!isInspectionEnabled(ref.getContainingFile(), ref.getProject())) return null;
      GrUnresolvedAccessInspection inspection =
          getInstance(ref.getContainingFile(), ref.getProject());

      if (!inspection.myHighlightIfGroovyObjectOverridden && areGroovyObjectMethodsOverridden(ref))
        return null;
      if (!inspection.myHighlightIfMissingMethodsDeclared && areMissingMethodsDeclared(ref))
        return null;

      if (GroovySuppressableInspectionTool.isElementToolSuppressedIn(ref, SHORT_NAME)) return null;
    }

    if (cannotBeDynamic || shouldHighlightAsUnresolved(ref)) {
      HighlightInfo info =
          createAnnotationForRef(
              ref, cannotBeDynamic, GroovyBundle.message("cannot.resolve", ref.getReferenceName()));
      LOG.assertTrue(info != null);

      HighlightDisplayKey displayKey = HighlightDisplayKey.find(SHORT_NAME);
      if (ref.getParent() instanceof GrMethodCall) {
        registerStaticImportFix(ref, info, displayKey);
      } else {
        registerCreateClassByTypeFix(ref, info, displayKey);
        registerAddImportFixes(ref, info, displayKey);
      }

      registerReferenceFixes(ref, info, cannotBeDynamic, displayKey);
      UnresolvedReferenceQuickFixProvider.registerReferenceFixes(
          ref, new QuickFixActionRegistrarAdapter(info, displayKey));
      OrderEntryFix.registerFixes(new QuickFixActionRegistrarAdapter(info, displayKey), ref);
      return info;
    }

    return null;
  }
  @Nullable
  private static HighlightInfo createAnnotationForRef(
      @NotNull GrReferenceExpression ref, boolean compileStatic, @NotNull String message) {
    PsiElement refNameElement = ref.getReferenceNameElement();
    assert refNameElement != null;

    HighlightDisplayLevel displayLevel = getHighlightDisplayLevel(ref.getProject(), ref);

    if (compileStatic || displayLevel == HighlightDisplayLevel.ERROR) {
      return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF)
          .range(refNameElement)
          .descriptionAndTooltip(message)
          .create();
    }

    if (displayLevel == HighlightDisplayLevel.WARNING) {
      boolean isTestMode = ApplicationManager.getApplication().isUnitTestMode();
      HighlightInfoType infotype =
          isTestMode ? HighlightInfoType.WARNING : HighlightInfoType.INFORMATION;

      HighlightInfo.Builder builder =
          HighlightInfo.newHighlightInfo(infotype).range(refNameElement);
      builder.descriptionAndTooltip(message);
      return builder.needsUpdateOnTyping(false).textAttributes(UNRESOLVED_ACCESS).create();
    }

    HighlightInfoType highlightInfoType = HighlightInfo.convertSeverity(displayLevel.getSeverity());
    return HighlightInfo.newHighlightInfo(highlightInfoType)
        .range(refNameElement)
        .descriptionAndTooltip(message)
        .create();
  }
 @Nullable
 private static PsiType getTypeFromMapAccess(@NotNull GrReferenceExpression ref) {
   // map access
   GrExpression qualifier = ref.getQualifierExpression();
   if (qualifier instanceof GrReferenceExpression) {
     if (((GrReferenceExpression) qualifier).resolve() instanceof PsiClass) return null;
   }
   if (qualifier != null) {
     PsiType qType = qualifier.getType();
     if (qType instanceof PsiClassType) {
       PsiClassType.ClassResolveResult qResult = ((PsiClassType) qType).resolveGenerics();
       PsiClass clazz = qResult.getElement();
       if (clazz != null) {
         PsiClass mapClass =
             JavaPsiFacade.getInstance(ref.getProject())
                 .findClass(CommonClassNames.JAVA_UTIL_MAP, ref.getResolveScope());
         if (mapClass != null && mapClass.getTypeParameters().length == 2) {
           PsiSubstitutor substitutor =
               TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor());
           if (substitutor != null) {
             PsiType substituted = substitutor.substitute(mapClass.getTypeParameters()[1]);
             if (substituted != null) {
               return PsiImplUtil.normalizeWildcardTypeByPosition(substituted, ref);
             }
           }
         }
       }
     }
   }
   return null;
 }
    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;
    }
  private static boolean findClassByText(GrReferenceExpression ref) {
    final String text = ref.getText();
    final int i = text.indexOf('<');
    String className = i == -1 ? text : text.substring(0, i);

    PsiClass[] names =
        PsiShortNamesCache.getInstance(ref.getProject())
            .getClassesByName(className, ref.getResolveScope());
    if (names.length > 0) return true;

    PsiFile file = ref.getContainingFile();
    if (file instanceof GroovyFile) {
      GrImportStatement[] imports = ((GroovyFile) file).getImportStatements();
      for (GrImportStatement anImport : imports) {
        if (className.equals(anImport.getImportedName())) return true;
      }
    }

    return false;
  }
 public static GrReferenceExpression qualifyReference(
     GrReferenceExpression referenceExpression,
     final PsiMember member,
     @Nullable final PsiClass qualifyingClass)
     throws IncorrectOperationException {
   PsiManager manager = referenceExpression.getManager();
   GrReferenceExpression expressionFromText;
   final GroovyPsiElementFactory factory =
       GroovyPsiElementFactory.getInstance(referenceExpression.getProject());
   if (qualifyingClass == null) {
     PsiClass parentClass = PsiTreeUtil.getParentOfType(referenceExpression, PsiClass.class);
     final PsiClass containingClass = member.getContainingClass();
     if (parentClass != null
         && !InheritanceUtil.isInheritorOrSelf(parentClass, containingClass, true)) {
       while (parentClass != null
           && !InheritanceUtil.isInheritorOrSelf(parentClass, containingClass, true)) {
         parentClass = PsiTreeUtil.getParentOfType(parentClass, PsiClass.class, true);
       }
       LOG.assertTrue(parentClass != null);
       expressionFromText =
           factory.createReferenceExpressionFromText("A.this." + member.getName());
       //noinspection ConstantConditions
       ((GrReferenceExpression) expressionFromText.getQualifier())
           .getQualifier()
           .replace(factory.createReferenceElementForClass(parentClass));
     } else {
       expressionFromText =
           (GrReferenceExpression) factory.createExpressionFromText("this." + member.getName());
     }
   } else {
     expressionFromText =
         (GrReferenceExpression) factory.createExpressionFromText("A." + member.getName());
     expressionFromText.setQualifier(factory.createReferenceElementForClass(qualifyingClass));
   }
   CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject());
   expressionFromText = (GrReferenceExpression) codeStyleManager.reformat(expressionFromText);
   return (GrReferenceExpression) referenceExpression.replace(expressionFromText);
 }
  private static boolean areGroovyObjectMethodsOverridden(GrReferenceExpression ref) {
    PsiType qualifierType = GrReferenceResolveUtil.getQualifierType(ref);
    if (!(qualifierType instanceof PsiClassType)) return false;

    PsiClass resolved = ((PsiClassType) qualifierType).resolve();
    if (resolved == null) return false;

    PsiClass groovyObject =
        JavaPsiFacade.getInstance(ref.getProject())
            .findClass(GroovyCommonClassNames.GROOVY_OBJECT, ref.getResolveScope());
    if (groovyObject == null) return false;

    String methodName;
    if (ref.getParent() instanceof GrCall) {
      methodName = "invokeMethod";
    } else if (PsiUtil.isLValue(ref)) {
      methodName = "setProperty";
    } else {
      methodName = "getProperty";
    }

    PsiMethod[] patternMethods = groovyObject.findMethodsByName(methodName, false);
    if (patternMethods.length != 1) return false;

    PsiMethod patternMethod = patternMethods[0];
    PsiMethod found = resolved.findMethodBySignature(patternMethod, true);
    if (found == null) return false;

    PsiClass aClass = found.getContainingClass();
    if (aClass == null) return false;
    String qname = aClass.getQualifiedName();
    if (GroovyCommonClassNames.GROOVY_OBJECT.equals(qname)) return false;
    if (GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT.equals(qname)) return false;

    return true;
  }