@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 PsiClassType getEnumSuperType(
     @NotNull PsiClass psiClass, @NotNull PsiElementFactory factory) {
   PsiClassType superType;
   final PsiManager manager = psiClass.getManager();
   final PsiClass enumClass =
       JavaPsiFacade.getInstance(manager.getProject())
           .findClass("java.lang.Enum", psiClass.getResolveScope());
   if (enumClass == null) {
     try {
       superType = (PsiClassType) factory.createTypeFromText("java.lang.Enum", null);
     } catch (IncorrectOperationException e) {
       superType = null;
     }
   } else {
     final PsiTypeParameter[] typeParameters = enumClass.getTypeParameters();
     PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
     if (typeParameters.length == 1) {
       substitutor = substitutor.put(typeParameters[0], factory.createType(psiClass));
     }
     superType = new PsiImmediateClassType(enumClass, substitutor);
   }
   return superType;
 }
 public static PsiSubstitutor obtainFinalSubstitutor(
     @NotNull PsiClass candidateClass,
     @NotNull PsiSubstitutor candidateSubstitutor,
     @NotNull PsiClass aClass,
     @NotNull PsiSubstitutor substitutor,
     @NotNull PsiElementFactory elementFactory,
     @NotNull LanguageLevel languageLevel) {
   if (PsiUtil.isRawSubstitutor(aClass, substitutor)) {
     return elementFactory.createRawSubstitutor(candidateClass);
   }
   final PsiType containingType =
       elementFactory.createType(candidateClass, candidateSubstitutor, languageLevel);
   PsiType type = substitutor.substitute(containingType);
   if (!(type instanceof PsiClassType)) return candidateSubstitutor;
   return ((PsiClassType) type).resolveGenerics().getSubstitutor();
 }
  @NotNull
  private static LookupElement castQualifier(
      @NotNull LookupElement item,
      @Nullable final PsiTypeLookupItem castTypeItem,
      @Nullable PsiType plainQualifier,
      JavaCompletionProcessor processor) {
    if (castTypeItem == null) {
      return item;
    }
    if (plainQualifier != null) {
      Object o = item.getObject();
      if (o instanceof PsiMethod) {
        PsiType castType = castTypeItem.getType();
        if (plainQualifier instanceof PsiClassType && castType instanceof PsiClassType) {
          PsiMethod method = (PsiMethod) o;
          PsiClassType.ClassResolveResult plainResult =
              ((PsiClassType) plainQualifier).resolveGenerics();
          PsiClass plainClass = plainResult.getElement();
          if (plainClass != null && plainClass.findMethodBySignature(method, true) != null) {
            PsiClass castClass = ((PsiClassType) castType).resolveGenerics().getElement();

            if (castClass == null || !castClass.isInheritor(plainClass, true)) {
              return item;
            }

            PsiSubstitutor plainSub = plainResult.getSubstitutor();
            PsiSubstitutor castSub =
                TypeConversionUtil.getSuperClassSubstitutor(plainClass, (PsiClassType) castType);
            PsiType returnType = method.getReturnType();
            if (method.getSignature(plainSub).equals(method.getSignature(castSub))) {
              PsiType typeAfterCast = toRaw(castSub.substitute(returnType));
              PsiType typeDeclared = toRaw(plainSub.substitute(returnType));
              if (typeAfterCast != null
                  && typeDeclared != null
                  && typeAfterCast.isAssignableFrom(typeDeclared)
                  && processor.isAccessible(plainClass.findMethodBySignature(method, true))) {
                return item;
              }
            }
          }
        }
      } else if (containsMember(plainQualifier, o)) {
        return item;
      }
    }

    return LookupElementDecorator.withInsertHandler(
        item,
        new InsertHandlerDecorator<LookupElement>() {
          @Override
          public void handleInsert(
              InsertionContext context, LookupElementDecorator<LookupElement> item) {
            final Document document = context.getEditor().getDocument();
            context.commitDocument();
            final PsiFile file = context.getFile();
            final PsiJavaCodeReferenceElement ref =
                PsiTreeUtil.findElementOfClassAtOffset(
                    file, context.getStartOffset(), PsiJavaCodeReferenceElement.class, false);
            if (ref != null) {
              final PsiElement qualifier = ref.getQualifier();
              if (qualifier != null) {
                final CommonCodeStyleSettings settings = context.getCodeStyleSettings();

                final String parenSpace = settings.SPACE_WITHIN_PARENTHESES ? " " : "";
                document.insertString(qualifier.getTextRange().getEndOffset(), parenSpace + ")");

                final String spaceWithin = settings.SPACE_WITHIN_CAST_PARENTHESES ? " " : "";
                final String prefix = "(" + parenSpace + "(" + spaceWithin;
                final String spaceAfter = settings.SPACE_AFTER_TYPE_CAST ? " " : "";
                final int exprStart = qualifier.getTextRange().getStartOffset();
                document.insertString(exprStart, prefix + spaceWithin + ")" + spaceAfter);

                CompletionUtil.emulateInsertion(context, exprStart + prefix.length(), castTypeItem);
                PsiDocumentManager.getInstance(file.getProject())
                    .doPostponedOperationsAndUnblockDocument(document);
                context.getEditor().getCaretModel().moveToOffset(context.getTailOffset());
              }
            }

            item.getDelegate().handleInsert(context);
          }
        });
  }