@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;
  }
    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;
    }
  @Nullable
  public static PsiType checkReassignedVar(
      GrReferenceExpression refExpr, boolean honorCompileStatic) {
    if (honorCompileStatic && !PsiUtil.isCompileStatic(refExpr) || refExpr.getQualifier() != null) {
      return null;
    }

    final PsiElement resolved = refExpr.resolve();
    if (!GroovyRefactoringUtil.isLocalVariable(resolved)) {
      return null;
    }

    assert resolved != null;
    return getLeastUpperBoundByVar((GrVariable) resolved);
  }