@Nullable
  public static PsiReferenceExpression createMockReference(
      final PsiElement place, @NotNull PsiType qualifierType, LookupElement qualifierItem) {
    PsiElementFactory factory = JavaPsiFacade.getElementFactory(place.getProject());
    if (qualifierItem.getObject() instanceof PsiClass) {
      final String qname = ((PsiClass) qualifierItem.getObject()).getQualifiedName();
      if (qname == null) return null;

      final String text = qname + ".xxx";
      try {
        final PsiExpression expr = factory.createExpressionFromText(text, place);
        if (expr instanceof PsiReferenceExpression) {
          return (PsiReferenceExpression) expr;
        }
        return null; // ignore ill-formed qualified names like "org.spark-project.jetty" that can't
                     // be used from Java code anyway
      } catch (IncorrectOperationException e) {
        LOG.info(e);
        return null;
      }
    }

    return (PsiReferenceExpression)
        factory.createExpressionFromText(
            "xxx.xxx", JavaCompletionUtil.createContextWithXxxVariable(place, qualifierType));
  }
 @Nullable
 public static List<? extends PsiElement> getAllPsiElements(final LookupElement item) {
   List<PsiMethod> allMethods = getAllMethods(item);
   if (allMethods != null) return allMethods;
   if (item.getObject() instanceof PsiElement)
     return Collections.singletonList((PsiElement) item.getObject());
   return null;
 }
  public static void checkCompletionContains(
      JavaCodeInsightTestFixture fixture, String... expectedVariants) {
    LookupElement[] lookupElements = fixture.completeBasic();

    Assert.assertNotNull(lookupElements);

    Set<String> missedVariants = CollectionFactory.hashSet(expectedVariants);

    for (LookupElement lookupElement : lookupElements) {
      String lookupString = lookupElement.getLookupString();
      missedVariants.remove(lookupString);

      Object object = lookupElement.getObject();
      if (object instanceof ResolveResult) {
        object = ((ResolveResult) object).getElement();
      }

      if (object instanceof PsiMethod) {
        missedVariants.remove(lookupString + "()");
      } else if (object instanceof PsiVariable) {
        missedVariants.remove('@' + lookupString);
      } else if (object instanceof NamedArgumentDescriptor) {
        missedVariants.remove(lookupString + ':');
      }
    }

    if (missedVariants.size() > 0) {
      Assert.assertTrue("Some completion variants are missed " + missedVariants, false);
    }
  }
 @NotNull
 @Override
 public Comparable weigh(@NotNull LookupElement item) {
   return item.getObject() instanceof PsiClass && !myAcceptClasses
       ? ExpectedTypeMatching.normal
       : getExpectedTypeMatching(item, myExpectedTypes);
 }
 @Nullable
 private Object getQualifierObject() {
   Object qObject = myQualifier.getObject();
   if (qObject instanceof ResolveResult) {
     qObject = ((ResolveResult) qObject).getElement();
   }
   return qObject;
 }
 @NotNull
 @Override
 public Comparable weigh(@NotNull LookupElement element) {
   final Object object = element.getObject();
   if (object instanceof PsiField) return -2;
   if (object instanceof PsiMethod && PropertyUtil.isSimplePropertyGetter((PsiMethod) object))
     return -1;
   return 0;
 }
    @NotNull
    @Override
    public MyResult weigh(@NotNull LookupElement item) {
      final Object object = item.getObject();

      if (object instanceof PsiClass) {
        if (object instanceof PsiTypeParameter) return MyResult.typeParameter;

        if (myTypeParameter != null
            && object.equals(
                PsiUtil.resolveClassInType(
                    TypeConversionUtil.typeParameterErasure(myTypeParameter)))) {
          return MyResult.exactlyExpected;
        }
      }

      if (myExpectedTypes == null) return MyResult.normal;

      PsiType itemType = JavaCompletionUtil.getLookupElementType(item);
      if (itemType == null || !itemType.isValid()) return MyResult.normal;

      if (object instanceof PsiClass) {
        for (final ExpectedTypeInfo info : myExpectedTypes) {
          if (TypeConversionUtil.erasure(info.getType().getDeepComponentType())
              .equals(TypeConversionUtil.erasure(itemType))) {
            return AbstractExpectedTypeSkipper.skips(item, myLocation)
                ? MyResult.expectedNoSelect
                : MyResult.exactlyExpected;
          }
        }
      }

      for (final ExpectedTypeInfo expectedInfo : myExpectedTypes) {
        final PsiType defaultType = expectedInfo.getDefaultType();
        final PsiType expectedType = expectedInfo.getType();
        if (!expectedType.isValid()) {
          return MyResult.normal;
        }

        if (defaultType != expectedType) {
          if (defaultType.equals(itemType)) {
            return MyResult.exactlyDefault;
          }

          if (defaultType.isAssignableFrom(itemType)) {
            return MyResult.ofDefaultType;
          }
        }
        if (PsiType.VOID.equals(itemType) && PsiType.VOID.equals(expectedType)) {
          return MyResult.exactlyExpected;
        }
      }

      return MyResult.normal;
    }
  public static boolean insertTail(
      InsertionContext context, LookupElement item, TailType tailType, boolean hasTail) {
    TailType toInsert = tailType;
    LookupItem<?> lookupItem = item.as(LookupItem.CLASS_CONDITION_KEY);
    if (lookupItem == null
        || lookupItem.getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) {
      if (!hasTail
          && item.getObject() instanceof PsiMethod
          && ((PsiMethod) item.getObject()).getReturnType() == PsiType.VOID) {
        PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments();
        if (psiElement()
            .beforeLeaf(psiElement().withText("."))
            .accepts(context.getFile().findElementAt(context.getTailOffset() - 1))) {
          return false;
        }

        boolean insertAdditionalSemicolon = true;
        final PsiReferenceExpression referenceExpression =
            PsiTreeUtil.getTopmostParentOfType(
                context.getFile().findElementAt(context.getStartOffset()),
                PsiReferenceExpression.class);
        if (referenceExpression instanceof PsiMethodReferenceExpression
            && LambdaHighlightingUtil.insertSemicolon(referenceExpression.getParent())) {
          insertAdditionalSemicolon = false;
        } else if (referenceExpression != null) {
          PsiElement parent = referenceExpression.getParent();
          if (parent instanceof PsiMethodCallExpression) {
            parent = parent.getParent();
          }
          if (parent instanceof PsiLambdaExpression
              && !LambdaHighlightingUtil.insertSemicolonAfter((PsiLambdaExpression) parent)) {
            insertAdditionalSemicolon = false;
          }
        }
        if (insertAdditionalSemicolon) {
          toInsert = TailType.SEMICOLON;
        }
      }
    }
    toInsert.processTail(context.getEditor(), context.getTailOffset());
    return true;
  }
    @NotNull
    @Override
    public Comparable weigh(@NotNull LookupElement element) {
      final Object object = element.getObject();
      final String name = getLookupObjectName(object);

      if (name != null && getNameEndMatchingDegree(name, myExpectedTypes) != 0) {
        return NameUtil.nameToWords(name).length - 1000;
      }
      return 0;
    }
 @Override
 public Object[] getParametersForLookup(LookupElement item, ParameterInfoContext context) {
   final Object o = item.getObject();
   if (o instanceof PsiElement) {
     final PsiElement element = (PsiElement) o;
     final DartComponentType type = DartComponentType.typeOf(element.getParent());
     if (type == DartComponentType.METHOD || type == DartComponentType.CONSTRUCTOR) {
       return new Object[] {element.getParent()};
     }
   }
   return ArrayUtil.EMPTY_OBJECT_ARRAY;
 }
 @Override
 public void handleInsert(InsertionContext context, LookupElement item) {
   super.handleInsert(context, item);
   final Object object = item.getObject();
   if (object instanceof JavaFxClassBackedElementDescriptor) {
     final XmlFile xmlFile = (XmlFile) context.getFile();
     final String shortName = ((JavaFxClassBackedElementDescriptor) object).getName();
     context.commitDocument();
     JavaFxPsiUtil.insertImportWhenNeeded(
         xmlFile, shortName, ((JavaFxClassBackedElementDescriptor) object).getQualifiedName());
   }
 }
  public Object[] getParametersForLookup(LookupElement item, ParameterInfoContext context) {
    final Object o = item.getObject();
    if (o instanceof PsiElement) {
      PsiElement element = (PsiElement) o;

      List<PsiElement> methods = new ArrayList<PsiElement>();
      if (element instanceof CfmlFunction || element instanceof PsiMethod) {
        methods.add(element);
      }
      return ArrayUtil.toObjectArray(methods);
    }
    return ArrayUtil.EMPTY_OBJECT_ARRAY;
  }
 @NotNull
 @Override
 public Comparable weigh(@NotNull LookupElement element) {
   final Object object = element.getObject();
   if (object instanceof PsiDocCommentOwner) {
     final PsiDocCommentOwner member = (PsiDocCommentOwner) object;
     if (!JavaPsiFacade.getInstance(member.getProject())
         .getResolveHelper()
         .isAccessible(member, myPosition, null)) return MyEnum.INACCESSIBLE;
     if (member.isDeprecated()) return MyEnum.DEPRECATED;
   }
   return MyEnum.NORMAL;
 }
  private static ExpectedTypeMatching getExpectedTypeMatching(
      LookupElement item, ExpectedTypeInfo[] expectedInfos) {
    PsiType itemType = JavaCompletionUtil.getLookupElementType(item);

    if (itemType != null) {
      for (final ExpectedTypeInfo expectedInfo : expectedInfos) {
        final PsiType defaultType = expectedInfo.getDefaultType();
        final PsiType expectedType = expectedInfo.getType();

        if (defaultType != expectedType && defaultType.isAssignableFrom(itemType)) {
          return ExpectedTypeMatching.ofDefaultType;
        }
        if (expectedType.isAssignableFrom(itemType)) {
          return ExpectedTypeMatching.expected;
        }
      }
    }

    boolean hasNonVoid = false;
    for (ExpectedTypeInfo info : expectedInfos) {
      if (!PsiType.VOID.equals(info.getType())) {
        hasNonVoid = true;
      }
    }

    if (hasNonVoid) {
      if (item.getObject() instanceof PsiKeyword) {
        String keyword = ((PsiKeyword) item.getObject()).getText();
        if (PsiKeyword.NEW.equals(keyword) || PsiKeyword.NULL.equals(keyword)) {
          return ExpectedTypeMatching.maybeExpected;
        }
      }
    } else if (expectedInfos.length > 0) {
      return ExpectedTypeMatching.unexpected;
    }

    return ExpectedTypeMatching.normal;
  }
Exemple #15
0
 private void addKeyword(
     Set<LookupElement> set,
     final TailType tailType,
     final Object comp,
     final PrefixMatcher matcher,
     final PsiFile file,
     final CompletionVariant variant) {
   for (final LookupElement item : set) {
     if (item.getObject().toString().equals(comp.toString())) {
       return;
     }
   }
   addLookupItem(set, tailType, comp, file, variant);
 }
  private static ExpectedTypeMatching getExpectedTypeMatching(
      LookupElement item, ExpectedTypeInfo[] expectedInfos, @Nullable String expectedMemberName) {
    PsiType itemType = JavaCompletionUtil.getLookupElementType(item);

    if (itemType != null) {
      PsiUtil.ensureValidType(itemType);

      for (final ExpectedTypeInfo expectedInfo : expectedInfos) {
        final PsiType defaultType = expectedInfo.getDefaultType();
        final PsiType expectedType = expectedInfo.getType();

        assert expectedType.isValid();
        assert defaultType.isValid();

        if (defaultType != expectedType && defaultType.isAssignableFrom(itemType)) {
          return ExpectedTypeMatching.ofDefaultType;
        }
        if (expectedType.isAssignableFrom(itemType)) {
          return ExpectedTypeMatching.expected;
        }
      }
    }

    if (hasNonVoid(expectedInfos)) {
      if (item.getObject() instanceof PsiKeyword) {
        String keyword = ((PsiKeyword) item.getObject()).getText();
        if (PsiKeyword.NEW.equals(keyword) || PsiKeyword.NULL.equals(keyword)) {
          return ExpectedTypeMatching.maybeExpected;
        }
      }
    } else if (expectedInfos.length > 0) {
      return ExpectedTypeMatching.unexpected;
    }

    return preferByMemberName(expectedMemberName, itemType);
  }
  @Nullable
  public static PsiElement getTargetElement(LookupElement lookupElement) {
    PsiElement psiElement = lookupElement.getPsiElement();
    if (psiElement != null) {
      return getOriginalElement(psiElement);
    }

    Object object = lookupElement.getObject();
    if (object instanceof LookupValueWithPsiElement) {
      final PsiElement element = ((LookupValueWithPsiElement) object).getElement();
      if (element != null) return getOriginalElement(element);
    }

    return null;
  }
  private static void suggestChainedCalls(
      CompletionParameters parameters, CompletionResultSet result, PsiElement position) {
    PsiElement parent = position.getParent();
    if (!(parent instanceof PsiJavaCodeReferenceElement)
        || parent.getParent() instanceof PsiImportStatementBase) {
      return;
    }
    PsiElement qualifier = ((PsiJavaCodeReferenceElement) parent).getQualifier();
    if (!(qualifier instanceof PsiJavaCodeReferenceElement)
        || ((PsiJavaCodeReferenceElement) qualifier).isQualified()) {
      return;
    }
    PsiElement target = ((PsiJavaCodeReferenceElement) qualifier).resolve();
    if (target != null && !(target instanceof PsiPackage)) {
      return;
    }

    PsiFile file = position.getContainingFile();
    if (file instanceof PsiJavaCodeReferenceCodeFragment) {
      return;
    }

    String fullPrefix =
        parent
            .getText()
            .substring(0, parameters.getOffset() - parent.getTextRange().getStartOffset());
    CompletionResultSet qualifiedCollector = result.withPrefixMatcher(fullPrefix);
    ElementFilter filter = JavaCompletionContributor.getReferenceFilter(position);
    for (LookupElement base :
        suggestQualifierItems(parameters, (PsiJavaCodeReferenceElement) qualifier, filter)) {
      PsiType type = JavaCompletionUtil.getLookupElementType(base);
      if (type != null && !PsiType.VOID.equals(type)) {
        PsiReferenceExpression ref =
            ReferenceExpressionCompletionContributor.createMockReference(position, type, base);
        if (ref != null) {
          for (final LookupElement item :
              JavaSmartCompletionContributor.completeReference(
                  position, ref, filter, true, true, parameters, result.getPrefixMatcher())) {
            qualifiedCollector.addElement(
                JavaCompletionUtil.highlightIfNeeded(
                    null, new JavaChainLookupElement(base, item), item.getObject(), position));
          }
        }
      }
    }
  }
    @NotNull
    @Override
    public ExpectedTypeMatching weigh(@NotNull LookupElement item) {
      if (item.getObject() instanceof PsiClass && !myConstructorPossible) {
        PsiType itemType = JavaCompletionUtil.getLookupElementType(item);
        if (itemType != null) {
          for (PsiType expectedClass : myExpectedClasses) {
            if (expectedClass.isAssignableFrom(itemType)) {
              return ExpectedTypeMatching.expected;
            }
          }
        }
        return preferByMemberName(myExpectedMemberName, itemType);
      }

      return getExpectedTypeMatching(item, myExpectedTypes, myExpectedMemberName);
    }
    @NotNull
    @Override
    public Comparable weigh(@NotNull LookupElement element) {
      if (element.getObject() instanceof PsiEnumConstant) return -2;

      if (!(myParameters.getOriginalFile() instanceof PsiJavaFile)) return -1;

      if (PsiKeyword.TRUE.equals(element.getLookupString())
          || PsiKeyword.FALSE.equals(element.getLookupString())) {
        boolean inReturn =
            PsiTreeUtil.getParentOfType(
                    myParameters.getPosition(), PsiReturnStatement.class, false, PsiMember.class)
                != null;
        return inReturn ? -2 : 0;
      }

      return -1;
    }
    @NotNull
    @Override
    public Comparable weigh(@NotNull LookupElement element) {
      final Object object = element.getObject();
      if (object instanceof PsiMethod) {
        PsiType type = ((PsiMethod) object).getReturnType();
        final JavaMethodCallElement callItem =
            element.as(JavaMethodCallElement.CLASS_CONDITION_KEY);
        if (callItem != null) {
          type = callItem.getSubstitutor().substitute(type);
        }

        if (type instanceof PsiClassType
            && ((PsiClassType) type).resolve() instanceof PsiTypeParameter) return 1;
      }

      return 0;
    }
  private int setTypeTextLabel(
      LookupElement item,
      final Color background,
      Color foreground,
      final LookupElementPresentation presentation,
      int allowedWidth,
      boolean selected,
      boolean nonFocusedSelection,
      FontMetrics normalMetrics) {
    final String givenText = presentation.getTypeText();
    final String labelText =
        trimLabelText(
            StringUtil.isEmpty(givenText) ? "" : " " + givenText, allowedWidth, normalMetrics);

    int used = RealLookupElementPresentation.getStringWidth(labelText, normalMetrics);

    final Icon icon = presentation.getTypeIcon();
    if (icon != null) {
      myTypeLabel.setIcon(icon);
      used += icon.getIconWidth();
    }

    Color sampleBackground = background;

    Object o = item.isValid() ? item.getObject() : null;
    //noinspection deprecation
    if (o instanceof LookupValueWithUIHint && StringUtil.isEmpty(labelText)) {
      //noinspection deprecation
      Color proposedBackground = ((LookupValueWithUIHint) o).getColorHint();
      if (proposedBackground != null) {
        sampleBackground = proposedBackground;
      }
      myTypeLabel.append("  ");
      used += normalMetrics.stringWidth("WW");
    } else {
      myTypeLabel.append(labelText);
    }

    myTypeLabel.setBackground(sampleBackground);
    myTypeLabel.setForeground(
        getTypeTextColor(item, foreground, presentation, selected, nonFocusedSelection));
    return used;
  }
  private static boolean insertingAnnotation(InsertionContext context, LookupElement item) {
    final Object obj = item.getObject();
    if (!(obj instanceof PsiClass) || !((PsiClass) obj).isAnnotationType()) return false;

    final Document document = context.getEditor().getDocument();
    PsiDocumentManager.getInstance(context.getProject()).commitDocument(document);
    final int offset = context.getStartOffset();

    final PsiFile file = context.getFile();

    if (PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiImportStatement.class, false)
        != null) return false;

    // outside of any class: we are surely inserting an annotation
    if (PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiClass.class, false) == null)
      return true;

    // the easiest check that there's a @ before the identifier
    return PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiAnnotation.class, false) != 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;
  }
 private static boolean insertingAnnotationWithParameters(
     InsertionContext context, LookupElement item) {
   if (insertingAnnotation(context, item)) {
     final Document document = context.getEditor().getDocument();
     PsiDocumentManager.getInstance(context.getProject()).commitDocument(document);
     PsiElement elementAt = context.getFile().findElementAt(context.getStartOffset());
     if (elementAt instanceof PsiIdentifier) {
       final PsiModifierListOwner parent =
           PsiTreeUtil.getParentOfType(
               elementAt, PsiModifierListOwner.class, false, PsiCodeBlock.class);
       if (parent != null) {
         for (PsiMethod m : ((PsiClass) item.getObject()).getMethods()) {
           if (!(m instanceof PsiAnnotationMethod)) continue;
           final PsiAnnotationMemberValue defaultValue =
               ((PsiAnnotationMethod) m).getDefaultValue();
           if (defaultValue == null) return true;
         }
       }
     }
   }
   return false;
 }
  private void doTestTagNameIcons(String fileName) throws IOException {
    VirtualFile file = copyFileToProject(fileName);
    myFixture.configureFromExistingVirtualFile(file);
    final LookupElement[] elements = myFixture.complete(CompletionType.BASIC);
    final Set<String> elementsToCheck =
        new HashSet<String>(Arrays.asList("view", "include", "requestFocus", "fragment", "Button"));

    for (LookupElement element : elements) {
      final String s = element.getLookupString();
      final Object obj = element.getObject();

      if (elementsToCheck.contains(s)) {
        LookupElementPresentation presentation = new LookupElementPresentation();
        element.renderElement(presentation);
        assertNotNull("no icon for element: " + element, presentation.getIcon());

        if ("Button".equals(s)) {
          assertInstanceOf(obj, PsiClass.class);
        }
      }
    }
  }
    @NotNull
    @Override
    public Comparable weigh(@NotNull LookupElement element) {
      final Object object = element.getObject();

      final String name = getLookupObjectName(object);
      if (name != null) {
        int max = 0;
        final List<String> wordsNoDigits = NameUtil.nameToWordsLowerCase(truncDigits(name));
        for (ExpectedTypeInfo myExpectedInfo : myExpectedTypes) {
          String expectedName = ((ExpectedTypeInfoImpl) myExpectedInfo).getExpectedName().compute();
          if (expectedName != null) {
            final THashSet<String> set =
                new THashSet<String>(NameUtil.nameToWordsLowerCase(truncDigits(expectedName)));
            set.retainAll(wordsNoDigits);
            max = Math.max(max, set.size());
          }
        }
        return -max;
      }
      return 0;
    }
  public static void insertParentheses(
      final InsertionContext context,
      final LookupElement item,
      boolean overloadsMatter,
      boolean hasParams,
      final boolean forceClosingParenthesis) {
    final Editor editor = context.getEditor();
    final char completionChar = context.getCompletionChar();
    final PsiFile file = context.getFile();

    final TailType tailType =
        completionChar == '('
            ? TailType.NONE
            : completionChar == ':'
                ? TailType.COND_EXPR_COLON
                : LookupItem.handleCompletionChar(context.getEditor(), item, completionChar);
    final boolean hasTail = tailType != TailType.NONE && tailType != TailType.UNKNOWN;
    final boolean smart = completionChar == Lookup.COMPLETE_STATEMENT_SELECT_CHAR;

    if (completionChar == '('
        || completionChar == '.'
        || completionChar == ','
        || completionChar == ';'
        || completionChar == ':'
        || completionChar == ' ') {
      context.setAddCompletionChar(false);
    }

    if (hasTail) {
      hasParams = false;
    }
    final boolean needRightParenth =
        forceClosingParenthesis
            || !smart
                && (CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET
                    || !hasParams && completionChar != '(');

    context.commitDocument();

    final CommonCodeStyleSettings styleSettings = context.getCodeStyleSettings();
    final PsiElement elementAt = file.findElementAt(context.getStartOffset());
    if (elementAt == null || !(elementAt.getParent() instanceof PsiMethodReferenceExpression)) {
      ParenthesesInsertHandler.getInstance(
              hasParams,
              styleSettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES,
              styleSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES && hasParams,
              needRightParenth,
              styleSettings.METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE)
          .handleInsert(context, item);
    }

    if (hasParams) {
      // Invoke parameters popup
      AutoPopupController.getInstance(file.getProject())
          .autoPopupParameterInfo(editor, overloadsMatter ? null : (PsiElement) item.getObject());
    }

    if (smart || !needRightParenth || !insertTail(context, item, tailType, hasTail)) {
      return;
    }

    if (completionChar == '.') {
      AutoPopupController.getInstance(file.getProject())
          .autoPopupMemberLookup(context.getEditor(), null);
    } else if (completionChar == ',') {
      AutoPopupController.getInstance(file.getProject())
          .autoPopupParameterInfo(context.getEditor(), null);
    }
  }
  @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);
          }
        });
  }
 @NotNull
 @Override
 public Comparable weigh(@NotNull LookupElement element) {
   final String name = getLookupObjectName(element.getObject());
   return -getNameEndMatchingDegree(name, myExpectedTypes);
 }