@Nullable
  public static GrExpression getRuntimeQualifier(GrReferenceExpression refExpr) {
    GrExpression qualifier = refExpr.getQualifierExpression();
    if (qualifier != null) return qualifier;

    for (GrClosableBlock closure = PsiTreeUtil.getParentOfType(refExpr, GrClosableBlock.class);
        closure != null;
        closure = PsiTreeUtil.getParentOfType(closure, GrClosableBlock.class)) {

      PsiElement parent = closure.getParent();
      if (parent instanceof GrArgumentList) parent = parent.getParent();
      if (!(parent instanceof GrMethodCall)) continue;

      GrExpression funExpr = ((GrMethodCall) parent).getInvokedExpression();
      if (!(funExpr instanceof GrReferenceExpression)) return funExpr;

      final PsiElement resolved = ((GrReferenceExpression) funExpr).resolve();
      if (!(resolved instanceof PsiMethod)) return funExpr;

      if (resolved instanceof GrGdkMethod
          && isFromDGM((GrGdkMethod) resolved)
          && !GdkMethodUtil.isWithName(((GrGdkMethod) resolved).getStaticMethod().getName())) {
        continue;
      }

      qualifier = ((GrReferenceExpression) funExpr).getQualifierExpression();
      if (qualifier != null) return qualifier;
    }

    return null;
  }
  @Override
  public Comparable weigh(@NotNull LookupElement element, @NotNull CompletionLocation location) {
    final PsiElement position = location.getCompletionParameters().getPosition();
    if (position.getLanguage() == GroovyFileType.GROOVY_LANGUAGE) return null;

    if (!(position.getParent() instanceof GrReferenceExpression)) return null;

    Object o = element.getObject();
    if (!(o instanceof GroovyResolveResult)) return 0;

    final PsiElement resolveContext = ((GroovyResolveResult) o).getCurrentFileResolveContext();

    if (resolveContext == null) return 0;

    if (GdkMethodUtil.isInWithContext(resolveContext)) {
      return 1;
    }

    return 0;
  }
  public boolean processMethods(
      PsiScopeProcessor processor, ResolveState state, PsiType qualifierType, Project project) {
    if (qualifierType == null) return true;

    NameHint nameHint = processor.getHint(NameHint.KEY);
    String name = nameHint == null ? null : nameHint.getName(state);
    final MultiMap<String, PsiMethod> map =
        name != null ? myOriginalMethodsByNameAndType.get(name) : myOriginalMethodByType.getValue();
    if (map.isEmpty()) {
      return true;
    }

    for (String superType : ResolveUtil.getAllSuperTypes(qualifierType, project).keySet()) {
      for (PsiMethod method : map.get(superType)) {
        String info = GdkMethodUtil.generateOriginInfo(method);
        GrGdkMethod gdk = GrGdkMethodImpl.createGdkMethod(method, myStatic, info);
        if (!processor.execute(gdk, state)) {
          return false;
        }
      }
    }

    return true;
  }
  @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;
  }
  @Nullable
  private PsiType getNominalTypeInner(@Nullable 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);
        }
      } else if (PsiUtil.isSuperReference(this)) {
        PsiClass contextClass = PsiUtil.getContextClass(this);
        if (GrTraitUtil.isTrait(contextClass)) {
          PsiClassType[] extendsTypes = contextClass.getExtendsListTypes();
          PsiClassType[] implementsTypes = contextClass.getImplementsListTypes();

          PsiClassType[] superTypes =
              ArrayUtil.mergeArrays(implementsTypes, extendsTypes, PsiClassType.ARRAY_FACTORY);

          return PsiIntersectionType.createIntersection(ArrayUtil.reverseArray(superTypes));
        }
        return factory.createType((PsiClass) resolved);
      }
      if (getParent() instanceof GrReferenceExpression) {
        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(
            PsiImplUtil.getQualifierType(this), getProject(), getResolveScope());
      }

      return PsiUtil.getSmartReturnType(method);
    }

    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;
  }