@Nullable
  private LocalQuickFix[] createNPEFixes(
      PsiExpression qualifier, PsiExpression expression, boolean onTheFly) {
    if (qualifier == null || expression == null) return null;
    if (qualifier instanceof PsiMethodCallExpression) return null;
    if (qualifier instanceof PsiLiteralExpression
        && ((PsiLiteralExpression) qualifier).getValue() == null) return null;

    try {
      final List<LocalQuickFix> fixes = new SmartList<LocalQuickFix>();

      if (PsiUtil.getLanguageLevel(qualifier).isAtLeast(LanguageLevel.JDK_1_4)) {
        final Project project = qualifier.getProject();
        final PsiElementFactory elementFactory =
            JavaPsiFacade.getInstance(project).getElementFactory();
        final PsiBinaryExpression binary =
            (PsiBinaryExpression) elementFactory.createExpressionFromText("a != null", null);
        binary.getLOperand().replace(qualifier);
        fixes.add(new AddAssertStatementFix(binary));
      }

      addSurroundWithIfFix(qualifier, fixes, onTheFly);

      if (ReplaceWithTernaryOperatorFix.isAvailable(qualifier, expression)) {
        fixes.add(new ReplaceWithTernaryOperatorFix(qualifier));
      }
      return fixes.toArray(new LocalQuickFix[fixes.size()]);
    } catch (IncorrectOperationException e) {
      LOG.error(e);
      return null;
    }
  }
  private static void addStatementKeywords(Consumer<LookupElement> variant, PsiElement position) {
    variant.consume(
        new OverrideableSpace(
            createKeyword(position, PsiKeyword.SWITCH), TailTypes.SWITCH_LPARENTH));
    variant.consume(
        new OverrideableSpace(createKeyword(position, PsiKeyword.WHILE), TailTypes.WHILE_LPARENTH));
    variant.consume(
        new OverrideableSpace(createKeyword(position, PsiKeyword.DO), TailTypes.DO_LBRACE));
    variant.consume(
        new OverrideableSpace(createKeyword(position, PsiKeyword.FOR), TailTypes.FOR_LPARENTH));
    variant.consume(
        new OverrideableSpace(createKeyword(position, PsiKeyword.IF), TailTypes.IF_LPARENTH));
    variant.consume(
        new OverrideableSpace(createKeyword(position, PsiKeyword.TRY), TailTypes.TRY_LBRACE));
    variant.consume(
        new OverrideableSpace(createKeyword(position, PsiKeyword.THROW), TailType.INSERT_SPACE));
    variant.consume(
        new OverrideableSpace(createKeyword(position, PsiKeyword.NEW), TailType.INSERT_SPACE));
    variant.consume(
        new OverrideableSpace(
            createKeyword(position, PsiKeyword.SYNCHRONIZED), TailTypes.SYNCHRONIZED_LPARENTH));

    if (PsiUtil.getLanguageLevel(position).isAtLeast(LanguageLevel.JDK_1_4)) {
      variant.consume(
          new OverrideableSpace(createKeyword(position, PsiKeyword.ASSERT), TailType.INSERT_SPACE));
    }

    TailType returnTail = getReturnTail(position);
    LookupElement ret = createKeyword(position, PsiKeyword.RETURN);
    if (returnTail != TailType.NONE) {
      ret = new OverrideableSpace(ret, returnTail);
    }
    variant.consume(ret);
  }
 @Nullable
 private static PsiType getExpectedTypeArg(
     PsiElement context,
     int index,
     PsiClassType.ClassResolveResult expectedType,
     PsiSubstitutor currentSubstitutor,
     PsiTypeParameter[] params) {
   PsiClass expectedClass = expectedType.getElement();
   assert expectedClass != null;
   for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(expectedClass)) {
     final PsiType argSubstitution = expectedType.getSubstitutor().substitute(parameter);
     final PsiType paramSubstitution = currentSubstitutor.substitute(parameter);
     final PsiType substitution =
         JavaPsiFacade.getInstance(context.getProject())
             .getResolveHelper()
             .getSubstitutionForTypeParameter(
                 params[index],
                 paramSubstitution,
                 argSubstitution,
                 false,
                 PsiUtil.getLanguageLevel(context));
     if (substitution != null && substitution != PsiType.NULL) {
       return substitution;
     }
   }
   return null;
 }
  /* Guesswork
   */
  @Nullable
  private static PsiSubstitutor getInheritorSubstitutorForNewExpression(
      final PsiClass baseClass,
      final PsiClass inheritor,
      final PsiSubstitutor baseSubstitutor,
      final PsiElement context) {
    final Project project = baseClass.getProject();
    JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
    final PsiResolveHelper resolveHelper = facade.getResolveHelper();
    PsiSubstitutor superSubstitutor =
        TypeConversionUtil.getClassSubstitutor(baseClass, inheritor, PsiSubstitutor.EMPTY);
    if (superSubstitutor == null) return null;
    PsiSubstitutor inheritorSubstitutor = PsiSubstitutor.EMPTY;
    for (PsiTypeParameter inheritorParameter : PsiUtil.typeParametersIterable(inheritor)) {
      for (PsiTypeParameter baseParameter : PsiUtil.typeParametersIterable(baseClass)) {
        final PsiType substituted = superSubstitutor.substitute(baseParameter);
        PsiType arg = baseSubstitutor.substitute(baseParameter);
        if (arg instanceof PsiWildcardType) arg = ((PsiWildcardType) arg).getBound();
        PsiType substitution =
            resolveHelper.getSubstitutionForTypeParameter(
                inheritorParameter, substituted, arg, true, PsiUtil.getLanguageLevel(context));
        if (PsiType.NULL.equals(substitution)) continue;
        if (substitution == null) {
          return facade.getElementFactory().createRawSubstitutor(inheritor);
        }
        inheritorSubstitutor = inheritorSubstitutor.put(inheritorParameter, substitution);
        break;
      }
    }

    return inheritorSubstitutor;
  }
 @NotNull
 @Override
 public PsiKeyword createKeyword(@NotNull @NonNls String keyword, PsiElement context)
     throws IncorrectOperationException {
   if (!JavaLexer.isKeyword(keyword, PsiUtil.getLanguageLevel(context))) {
     throw new IncorrectOperationException("\"" + keyword + "\" is not a keyword.");
   }
   return new LightKeyword(myManager, keyword);
 }
 @Override
 public boolean processDeclarations(
     @NotNull final PsiScopeProcessor processor,
     @NotNull final ResolveState state,
     final PsiElement lastParent,
     @NotNull final PsiElement place) {
   return PsiClassImplUtil.processDeclarationsInClass(
       this, processor, state, null, lastParent, place, PsiUtil.getLanguageLevel(place), false);
 }
 private static PsiType getExpandedType(PsiType type, @NotNull PsiElement typeElement) {
   if (type instanceof PsiArrayType) {
     type =
         JavaPsiFacade.getElementFactory(typeElement.getProject())
             .getArrayClassType(
                 ((PsiArrayType) type).getComponentType(), PsiUtil.getLanguageLevel(typeElement));
   }
   return type;
 }
Ejemplo n.º 8
0
  private static boolean changeClassTypeArgument(
      PsiMethod myMethod,
      Project project,
      PsiType superReturnType,
      PsiClass superClass,
      Editor editor,
      PsiType returnType) {
    if (superClass == null || !superClass.hasTypeParameters()) return true;
    final PsiClass superReturnTypeClass = PsiUtil.resolveClassInType(superReturnType);
    if (superReturnTypeClass == null
        || !(superReturnTypeClass instanceof PsiTypeParameter
            || superReturnTypeClass.hasTypeParameters())) return true;

    final PsiClass derivedClass = myMethod.getContainingClass();
    if (derivedClass == null) return true;

    final PsiReferenceParameterList referenceParameterList =
        findTypeArgumentsList(superClass, derivedClass);
    if (referenceParameterList == null) return true;

    final PsiElement resolve =
        ((PsiJavaCodeReferenceElement) referenceParameterList.getParent()).resolve();
    if (!(resolve instanceof PsiClass)) return true;
    final PsiClass baseClass = (PsiClass) resolve;

    if (returnType instanceof PsiPrimitiveType) {
      returnType = ((PsiPrimitiveType) returnType).getBoxedType(derivedClass);
    }

    final PsiSubstitutor superClassSubstitutor =
        TypeConversionUtil.getSuperClassSubstitutor(superClass, baseClass, PsiSubstitutor.EMPTY);
    final PsiType superReturnTypeInBaseClassType =
        superClassSubstitutor.substitute(superReturnType);
    final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
    final PsiSubstitutor psiSubstitutor =
        resolveHelper.inferTypeArguments(
            PsiTypesUtil.filterUnusedTypeParameters(
                superReturnTypeInBaseClassType, baseClass.getTypeParameters()),
            new PsiType[] {superReturnTypeInBaseClassType},
            new PsiType[] {returnType},
            PsiUtil.getLanguageLevel(superClass));

    final TypeMigrationRules rules = new TypeMigrationRules();
    final PsiSubstitutor compoundSubstitutor =
        TypeConversionUtil.getSuperClassSubstitutor(superClass, derivedClass, PsiSubstitutor.EMPTY)
            .putAll(psiSubstitutor);
    rules.setBoundScope(new LocalSearchScope(derivedClass));
    TypeMigrationProcessor.runHighlightingTypeMigration(
        project,
        editor,
        rules,
        referenceParameterList,
        JavaPsiFacade.getElementFactory(project).createType(baseClass, compoundSubstitutor));

    return false;
  }
  @Override
  public boolean processDeclarations(
      @NotNull PsiScopeProcessor processor,
      @NotNull ResolveState state,
      PsiElement lastParent,
      @NotNull PsiElement place) {
    GlobalSearchScope scope = place.getResolveScope();

    processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this);
    ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);

    final JavaPsiFacade facade = getFacade();
    final Condition<String> prefixMatcher = processor.getHint(JavaCompletionHints.NAME_FILTER);

    if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) {
      NameHint nameHint = processor.getHint(NameHint.KEY);
      if (nameHint != null) {
        final String shortName = nameHint.getName(state);
        if (containsClassNamed(shortName)
            && processClassesByName(processor, state, scope, shortName)) return false;
      } else if (prefixMatcher != null) {
        for (String className : getClassNamesCache()) {
          if (prefixMatcher.value(className)) {
            if (processClassesByName(processor, state, scope, className)) return false;
          }
        }
      } else {
        PsiClass[] classes = getClasses(scope);
        if (!processClasses(processor, state, classes)) return false;
      }
    }
    if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.PACKAGE)) {
      NameHint nameHint = processor.getHint(NameHint.KEY);
      if (nameHint != null) {
        PsiPackage aPackage = findSubPackageByName(nameHint.getName(state));
        if (aPackage != null) {
          if (!processor.execute(aPackage, state)) return false;
        }
      } else {
        PsiPackage[] packs = getSubPackages(scope);
        for (PsiPackage pack : packs) {
          final String packageName = pack.getName();
          if (packageName == null) continue;
          if (!facade.getNameHelper().isIdentifier(packageName, PsiUtil.getLanguageLevel(this))) {
            continue;
          }
          if (!processor.execute(pack, state)) {
            return false;
          }
        }
      }
    }
    return true;
  }
  private static boolean shouldMarkRed(@NotNull Object object, @NotNull PsiElement place) {
    if (!(object instanceof PsiMember)) return false;
    if (Java15APIUsageInspectionBase.isForbiddenApiUsage(
        (PsiMember) object, PsiUtil.getLanguageLevel(place))) return true;

    if (object instanceof PsiEnumConstant) {
      return findConstantsUsedInSwitch(place)
          .contains(CompletionUtil.getOriginalOrSelf((PsiEnumConstant) object));
    }
    return false;
  }
Ejemplo n.º 11
0
  @Override
  public boolean processDeclarations(
      @NotNull PsiScopeProcessor processor,
      @NotNull ResolveState state,
      PsiElement lastParent,
      @NotNull PsiElement place) {
    GlobalSearchScope scope = place.getResolveScope();

    processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this);
    ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);

    final Condition<String> nameCondition = processor.getHint(JavaCompletionHints.NAME_FILTER);

    if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) {
      NameHint nameHint = processor.getHint(NameHint.KEY);
      if (nameHint != null) {
        final String shortName = nameHint.getName(state);
        final PsiClass[] classes = findClassByShortName(shortName, scope);
        if (!processClasses(processor, state, classes, Conditions.<String>alwaysTrue()))
          return false;
      } else {
        PsiClass[] classes = getClasses(scope);
        if (!processClasses(
            processor,
            state,
            classes,
            nameCondition != null ? nameCondition : Conditions.<String>alwaysTrue())) return false;
      }
    }
    if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.PACKAGE)) {
      NameHint nameHint = processor.getHint(NameHint.KEY);
      if (nameHint != null) {
        PsiPackage aPackage = findSubPackageByName(nameHint.getName(state));
        if (aPackage != null) {
          if (!processor.execute(aPackage, state)) return false;
        }
      } else {
        PsiPackage[] packs = getSubPackages(scope);
        for (PsiPackage pack : packs) {
          final String packageName = pack.getName();
          if (packageName == null) continue;
          if (!PsiNameHelper.getInstance(myManager.getProject())
              .isIdentifier(packageName, PsiUtil.getLanguageLevel(this))) {
            continue;
          }
          if (!processor.execute(pack, state)) {
            return false;
          }
        }
      }
    }
    return true;
  }
    @Override
    @Nullable
    public PsiType fun(final PsiMethodCallExpression call) {
      PsiReferenceExpression methodExpression = call.getMethodExpression();
      PsiType theOnly = null;
      final JavaResolveResult[] results = methodExpression.multiResolve(false);
      LanguageLevel languageLevel = PsiUtil.getLanguageLevel(call);

      final PsiElement callParent = PsiUtil.skipParenthesizedExprUp(call.getParent());
      final PsiExpressionList parentArgList;
      if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
        parentArgList =
            callParent instanceof PsiConditionalExpression
                    && !PsiPolyExpressionUtil.isPolyExpression((PsiExpression) callParent)
                ? null
                : PsiTreeUtil.getParentOfType(call, PsiExpressionList.class);
      } else {
        parentArgList = null;
      }
      final MethodCandidateInfo.CurrentCandidateProperties properties =
          MethodCandidateInfo.getCurrentMethod(parentArgList);
      final boolean genericMethodCall =
          properties != null && properties.getInfo().isToInferApplicability();

      for (int i = 0; i < results.length; i++) {
        final JavaResolveResult candidateInfo = results[i];

        if (genericMethodCall
            && PsiPolyExpressionUtil.isMethodCallPolyExpression(
                call, (PsiMethod) candidateInfo.getElement())) {
          if (callParent instanceof PsiAssignmentExpression) {
            return null;
          }
          LOG.error("poly expression evaluation during overload resolution");
        }

        final PsiType type = getResultType(call, methodExpression, candidateInfo, languageLevel);
        if (type == null) {
          return null;
        }

        if (i == 0) {
          theOnly = type;
        } else if (!theOnly.equals(type)) {
          return null;
        }
      }

      return PsiClassImplUtil.correctType(theOnly, call.getResolveScope());
    }
Ejemplo n.º 13
0
  @Override
  public ASTNode parseContents(final ASTNode chameleon) {
    if (JavaParserDefinition.USE_NEW_PARSER) {
      final PsiBuilder builder = JavaParserUtil.createBuilder(chameleon);
      doParse(builder);
      return builder.getTreeBuilt().getFirstChildNode();
    }

    FileElement node = (FileElement) chameleon;
    final CharSequence seq = node.getChars();

    final PsiManager manager = node.getManager();
    final JavaLexer lexer = new JavaLexer(PsiUtil.getLanguageLevel(node.getPsi()));
    return FileTextParsing.parseFileText(manager, lexer, seq, 0, seq.length(), node.getCharTable());
  }
  private static boolean shouldMarkRed(@NotNull Object object, @NotNull PsiElement place) {
    if (!(object instanceof PsiMember)) return false;
    if (Java15APIUsageInspectionBase.isForbiddenApiUsage(
        (PsiMember) object, PsiUtil.getLanguageLevel(place))) return true;

    if (object instanceof PsiEnumConstant) {
      return findConstantsUsedInSwitch(place)
          .contains(CompletionUtil.getOriginalOrSelf((PsiEnumConstant) object));
    }
    if (object instanceof PsiClass
        && ReferenceListWeigher.INSTANCE.getApplicability((PsiClass) object, place)
            == inapplicable) {
      return true;
    }
    return false;
  }
  /**
   * Returns a boxed class type corresponding to the primitive type.
   *
   * @param context where this boxed type is to be used
   * @return the class type, or null if the current language level does not support autoboxing or it
   *     was not possible to resolve the reference to the class.
   */
  @Nullable
  public PsiClassType getBoxedType(PsiElement context) {
    PsiFile file = context.getContainingFile();
    LanguageLevel languageLevel = PsiUtil.getLanguageLevel(file);
    if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) return null;

    String boxedQName = getBoxedTypeName();
    // [ven]previous call returns null for NULL, VOID
    if (boxedQName == null) return null;
    JavaPsiFacade facade = JavaPsiFacade.getInstance(file.getProject());
    PsiClass aClass = facade.findClass(boxedQName, context.getResolveScope());
    if (aClass == null) return null;

    PsiElementFactory factory = facade.getElementFactory();
    return factory.createType(aClass, PsiSubstitutor.EMPTY, languageLevel, getAnnotations());
  }
  public static String checkReturnType(
      PsiMethodReferenceExpression expression,
      JavaResolveResult result,
      PsiType functionalInterfaceType) {
    final PsiElement resolve = result.getElement();
    if (resolve instanceof PsiMethod) {
      final PsiClass containingClass = ((PsiMethod) resolve).getContainingClass();
      LOG.assertTrue(containingClass != null);
      PsiSubstitutor subst = result.getSubstitutor();
      PsiClass qContainingClass = getQualifierResolveResult(expression).getContainingClass();
      if (qContainingClass != null
          && isReceiverType(functionalInterfaceType, containingClass, (PsiMethod) resolve)) {
        subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst);
        LOG.assertTrue(subst != null);
      }

      final PsiType interfaceReturnType =
          LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);

      PsiType returnType =
          PsiTypesUtil.patchMethodGetClassReturnType(
              expression,
              expression,
              (PsiMethod) resolve,
              null,
              PsiUtil.getLanguageLevel(expression));
      if (returnType == null) {
        returnType = ((PsiMethod) resolve).getReturnType();
      }
      PsiType methodReturnType = subst.substitute(returnType);
      if (interfaceReturnType != null && interfaceReturnType != PsiType.VOID) {
        if (methodReturnType == null) {
          methodReturnType =
              JavaPsiFacade.getElementFactory(expression.getProject())
                  .createType(containingClass, subst);
        }
        if (!TypeConversionUtil.isAssignable(interfaceReturnType, methodReturnType, false)) {
          return "Bad return type in method reference: cannot convert "
              + methodReturnType.getCanonicalText()
              + " to "
              + interfaceReturnType.getCanonicalText();
        }
      }
    }
    return null;
  }
  private static void addKeywords(CompletionParameters parameters, CompletionResultSet result) {
    PsiElement position = parameters.getPosition();
    final Set<LookupElement> lookupSet = new LinkedHashSet<LookupElement>();
    final Set<CompletionVariant> keywordVariants = new HashSet<CompletionVariant>();
    final JavaCompletionData completionData = getCompletionData(PsiUtil.getLanguageLevel(position));
    completionData.addKeywordVariants(keywordVariants, position, parameters.getOriginalFile());
    completionData.completeKeywordsBySet(
        lookupSet,
        keywordVariants,
        position,
        result.getPrefixMatcher(),
        parameters.getOriginalFile());
    completionData.fillCompletions(parameters, result);

    for (final LookupElement item : lookupSet) {
      result.addElement(item);
    }
  }
 private static PsiSubstitutor getSuperClassSubstitutor(
     final PsiType superClassType,
     final PsiClassType targetClassType,
     final PsiResolveHelper resolveHelper,
     PsiClass targetClass) {
   PsiSubstitutor subst = PsiSubstitutor.EMPTY;
   for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(targetClass)) {
     subst =
         subst.put(
             typeParameter,
             resolveHelper.getSubstitutionForTypeParameter(
                 typeParameter,
                 targetClassType,
                 superClassType,
                 false,
                 PsiUtil.getLanguageLevel(targetClass)));
   }
   return subst;
 }
  public static boolean processDeclarationsInClass(
      @NotNull PsiClass aClass,
      @NotNull final PsiScopeProcessor processor,
      @NotNull ResolveState state,
      @Nullable Set<PsiClass> visited,
      PsiElement last,
      @NotNull PsiElement place,
      boolean isRaw) {
    if (last instanceof PsiTypeParameterList || last instanceof PsiModifierList) {
      return true; // TypeParameterList and ModifierList do not see our declarations
    }
    if (visited != null && visited.contains(aClass)) return true;

    PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
    isRaw = isRaw || PsiUtil.isRawSubstitutor(aClass, substitutor);

    ParameterizedCachedValue<MembersMap, PsiClass> cache =
        getValues(aClass); // aClass.getUserData(MAP_IN_CLASS_KEY);
    boolean upToDate = cache.hasUpToDateValue();
    LanguageLevel languageLevel = PsiUtil.getLanguageLevel(place);
    if (
    /*true || */ upToDate) {
      final NameHint nameHint = processor.getHint(NameHint.KEY);
      if (nameHint != null) {
        String name = nameHint.getName(state);
        return processCachedMembersByName(
            aClass,
            processor,
            state,
            visited,
            last,
            place,
            isRaw,
            substitutor,
            cache.getValue(aClass),
            name,
            languageLevel);
      }
    }
    return processDeclarationsInClassNotCached(
        aClass, processor, state, visited, last, place, isRaw, languageLevel);
  }
Ejemplo n.º 20
0
  @NotNull
  public static PsiAnnotationMemberValue createMemberValueFromText(
      final String text, final PsiManager manager, final ClsElementImpl parent) {
    final PsiElementFactory factory =
        JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
    final PsiJavaFile context =
        ((PsiJavaParserFacadeImpl) factory).getDummyJavaFile(); // to resolve classes from java.lang
    final LanguageLevel level = PsiUtil.getLanguageLevel(parent);
    final DummyHolder holder =
        DummyHolderFactory.createHolder(
            manager, new JavaDummyElement(text, ANNOTATION_VALUE, level), context);
    final PsiElement element =
        SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
    if (!(element instanceof PsiAnnotationMemberValue)) {
      LOG.error("Could not parse initializer:'" + text + "'");
      return null;
    }

    return getMemberValue(element, parent);
  }
  @NotNull
  private static MembersMap buildAllMaps(@NotNull PsiClass psiClass) {
    final List<Pair<PsiMember, PsiSubstitutor>> classes =
        new ArrayList<Pair<PsiMember, PsiSubstitutor>>();
    final List<Pair<PsiMember, PsiSubstitutor>> fields =
        new ArrayList<Pair<PsiMember, PsiSubstitutor>>();
    final List<Pair<PsiMember, PsiSubstitutor>> methods =
        new ArrayList<Pair<PsiMember, PsiSubstitutor>>();

    FilterScopeProcessor<MethodCandidateInfo> processor =
        new FilterScopeProcessor<MethodCandidateInfo>(
            new OrFilter(
                ElementClassFilter.METHOD, ElementClassFilter.FIELD, ElementClassFilter.CLASS)) {
          @Override
          protected void add(PsiElement element, PsiSubstitutor substitutor) {
            if (element instanceof PsiMethod) {
              methods.add(Pair.create((PsiMember) element, substitutor));
            } else if (element instanceof PsiField) {
              fields.add(Pair.create((PsiMember) element, substitutor));
            } else if (element instanceof PsiClass) {
              classes.add(Pair.create((PsiMember) element, substitutor));
            }
          }
        };
    processDeclarationsInClassNotCached(
        psiClass,
        processor,
        ResolveState.initial(),
        null,
        null,
        psiClass,
        false,
        PsiUtil.getLanguageLevel(psiClass));

    MembersMap result = new MembersMap(MemberType.class);
    result.put(MemberType.CLASS, generateMapByList(classes));
    result.put(MemberType.METHOD, generateMapByList(methods));
    result.put(MemberType.FIELD, generateMapByList(fields));
    return result;
  }
  public void handleInsert(
      final InsertionContext context, final JavaPsiClassReferenceElement item) {
    final char c = context.getCompletionChar();

    int offset = context.getTailOffset() - 1;
    final PsiFile file = context.getFile();
    if (PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiImportStatementBase.class, false)
        != null) {
      final PsiJavaCodeReferenceElement ref =
          PsiTreeUtil.findElementOfClassAtOffset(
              file, offset, PsiJavaCodeReferenceElement.class, false);
      final String qname = item.getQualifiedName();
      if (qname != null && (ref == null || !qname.equals(ref.getCanonicalText()))) {
        AllClassesGetter.INSERT_FQN.handleInsert(context, item);
      }
      return;
    }

    PsiElement position = file.findElementAt(offset);
    PsiClass psiClass = item.getObject();
    final Project project = context.getProject();
    final boolean annotation = insertingAnnotation(context, item);

    final Editor editor = context.getEditor();
    if (c == '#') {
      context.setLaterRunnable(
          new Runnable() {
            public void run() {
              new CodeCompletionHandlerBase(CompletionType.BASIC).invokeCompletion(project, editor);
            }
          });
    } else if (c == '.' && PsiTreeUtil.getParentOfType(position, PsiParameterList.class) == null) {
      AutoPopupController.getInstance(context.getProject())
          .autoPopupMemberLookup(context.getEditor(), null);
    }

    if (position != null) {
      PsiElement parent = position.getParent();
      if (parent instanceof PsiJavaCodeReferenceElement) {
        final PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement) parent;
        if (PsiTreeUtil.getParentOfType(position, PsiDocTag.class) != null
            && ref.isReferenceTo(psiClass)) {
          return;
        }
      }
    }

    OffsetKey refEnd = context.trackOffset(context.getTailOffset(), false);

    boolean fillTypeArgs = context.getCompletionChar() == '<';
    if (fillTypeArgs) {
      context.setAddCompletionChar(false);
    }

    if (shouldInsertParentheses(psiClass, position)) {
      if (ConstructorInsertHandler.insertParentheses(context, item, psiClass, false)) {
        fillTypeArgs |=
            psiClass.hasTypeParameters()
                && PsiUtil.getLanguageLevel(file).isAtLeast(LanguageLevel.JDK_1_5);
      }
    } else if (insertingAnnotationWithParameters(context, item)) {
      JavaCompletionUtil.insertParentheses(context, item, false, true);
      AutoPopupController.getInstance(project).autoPopupParameterInfo(editor, null);
    }

    LOG.assertTrue(context.getTailOffset() >= 0);
    String docText = context.getDocument().getText();
    DefaultInsertHandler.addImportForItem(context, item);
    if (context.getTailOffset() < 0) {
      LOG.error(
          LogMessageEx.createEvent(
              "Tail offset degraded after insertion",
              "start=" + context.getStartOffset(),
              new Attachment(
                  context.getFile().getViewProvider().getVirtualFile().getPath(), docText)));
    }

    if (annotation) {
      // Check if someone inserts annotation class that require @
      PsiElement elementAt = file.findElementAt(context.getStartOffset());
      final PsiElement parentElement = elementAt != null ? elementAt.getParent() : null;

      if (elementAt instanceof PsiIdentifier
          && (PsiTreeUtil.getParentOfType(elementAt, PsiAnnotationParameterList.class) != null
              || parentElement instanceof PsiErrorElement
                  && parentElement.getParent()
                      instanceof PsiJavaFile // top level annotation without @
          )
          && isAtTokenNeeded(context)) {
        int expectedOffsetForAtToken = elementAt.getTextRange().getStartOffset();
        context.getDocument().insertString(expectedOffsetForAtToken, "@");
      }
    }

    if (fillTypeArgs) {
      PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();
      int typeArgs = context.getOffset(refEnd);
      if (typeArgs >= 0) {
        context.getDocument().insertString(typeArgs, "<>");
        context.getEditor().getCaretModel().moveToOffset(typeArgs + 1);
      }
    }
  }
  public void fillCompletions(
      CompletionParameters parameters, final Consumer<LookupElement> result) {
    final PsiElement position = parameters.getPosition();
    if (PsiTreeUtil.getParentOfType(position, PsiComment.class, false) != null) {
      return;
    }

    PsiStatement statement = PsiTreeUtil.getParentOfType(position, PsiExpressionStatement.class);
    if (statement == null) {
      statement = PsiTreeUtil.getParentOfType(position, PsiDeclarationStatement.class);
    }
    PsiElement prevLeaf = PsiTreeUtil.prevVisibleLeaf(position);
    if (statement != null
        && statement.getTextRange().getStartOffset() == position.getTextRange().getStartOffset()) {
      if (!psiElement()
          .withSuperParent(2, PsiSwitchStatement.class)
          .afterLeaf("{")
          .accepts(statement)) {
        PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(prevLeaf, PsiTryStatement.class);
        if (tryStatement == null
            || tryStatement.getCatchSections().length > 0
            || tryStatement.getFinallyBlock() != null) {
          result.consume(
              new OverrideableSpace(
                  createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD));
        }
      }
    }

    if (isStatementPosition(position)) {
      if (PsiTreeUtil.getParentOfType(position, PsiSwitchStatement.class, false, PsiMember.class)
          != null) {
        result.consume(
            new OverrideableSpace(createKeyword(position, PsiKeyword.CASE), TailType.INSERT_SPACE));
        result.consume(
            new OverrideableSpace(
                createKeyword(position, PsiKeyword.DEFAULT), TailType.CASE_COLON));
        if (START_SWITCH.accepts(position)) {
          return;
        }
      }

      addBreakContinue(result, position);
      addStatementKeywords(result, position);
    }

    if (SUPER_OR_THIS_PATTERN.accepts(position)) {
      final boolean afterDot = AFTER_DOT.accepts(position);
      final boolean insideQualifierClass = isInsideQualifierClass(position);
      final boolean insideInheritorClass =
          PsiUtil.isLanguageLevel8OrHigher(position) && isInsideInheritorClass(position);
      if (!afterDot || insideQualifierClass || insideInheritorClass) {
        if (!afterDot || insideQualifierClass) {
          result.consume(createKeyword(position, PsiKeyword.THIS));
        }

        final LookupItem superItem = (LookupItem) createKeyword(position, PsiKeyword.SUPER);
        if (psiElement()
            .afterLeaf(psiElement().withText("{").withSuperParent(2, psiMethod().constructor(true)))
            .accepts(position)) {
          final PsiMethod method =
              PsiTreeUtil.getParentOfType(position, PsiMethod.class, false, PsiClass.class);
          assert method != null;
          final boolean hasParams = superConstructorHasParameters(method);
          superItem.setInsertHandler(
              new ParenthesesInsertHandler<LookupElement>() {
                @Override
                protected boolean placeCaretInsideParentheses(
                    InsertionContext context, LookupElement item) {
                  return hasParams;
                }

                @Override
                public void handleInsert(InsertionContext context, LookupElement item) {
                  super.handleInsert(context, item);
                  TailType.insertChar(context.getEditor(), context.getTailOffset(), ';');
                }
              });
        }

        result.consume(superItem);
      }
    }

    if (isExpressionPosition(position)) {
      if (PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) == null) {
        result.consume(
            TailTypeDecorator.withTail(
                createKeyword(position, PsiKeyword.NEW), TailType.INSERT_SPACE));
        result.consume(createKeyword(position, PsiKeyword.NULL));
      }
      if (mayExpectBoolean(parameters)) {
        result.consume(createKeyword(position, PsiKeyword.TRUE));
        result.consume(createKeyword(position, PsiKeyword.FALSE));
      }
    }

    PsiFile file = position.getContainingFile();
    if (!(file instanceof PsiExpressionCodeFragment)
        && !(file instanceof PsiJavaCodeReferenceCodeFragment)
        && !(file instanceof PsiTypeCodeFragment)) {
      if (prevLeaf == null) {
        result.consume(
            new OverrideableSpace(
                createKeyword(position, PsiKeyword.PACKAGE), TailType.HUMBLE_SPACE_BEFORE_WORD));
        result.consume(
            new OverrideableSpace(
                createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD));
      } else if (END_OF_BLOCK.getValue().isAcceptable(position, position)
          && PsiTreeUtil.getParentOfType(position, PsiMember.class) == null) {
        result.consume(
            new OverrideableSpace(
                createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD));
      }
    }

    if ((isInsideParameterList(position)
            || isAtResourceVariableStart(position)
            || isAtCatchVariableStart(position))
        && !psiElement().afterLeaf(PsiKeyword.FINAL).accepts(position)
        && !AFTER_DOT.accepts(position)) {
      result.consume(
          TailTypeDecorator.withTail(
              createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD));
    }

    if (isInstanceofPlace(position)) {
      result.consume(
          LookupElementDecorator.withInsertHandler(
              createKeyword(position, PsiKeyword.INSTANCEOF),
              new InsertHandler<LookupElementDecorator<LookupElement>>() {
                @Override
                public void handleInsert(
                    InsertionContext context, LookupElementDecorator<LookupElement> item) {
                  TailType tailType = TailType.HUMBLE_SPACE_BEFORE_WORD;
                  if (tailType.isApplicable(context)) {
                    tailType.processTail(context.getEditor(), context.getTailOffset());
                  }

                  if ('!' == context.getCompletionChar()) {
                    context.setAddCompletionChar(false);
                    context.commitDocument();
                    PsiInstanceOfExpression expr =
                        PsiTreeUtil.findElementOfClassAtOffset(
                            context.getFile(),
                            context.getStartOffset(),
                            PsiInstanceOfExpression.class,
                            false);
                    if (expr != null) {
                      String space =
                          context.getCodeStyleSettings().SPACE_WITHIN_PARENTHESES ? " " : "";
                      context
                          .getDocument()
                          .insertString(expr.getTextRange().getStartOffset(), "!(" + space);
                      context.getDocument().insertString(context.getTailOffset(), space + ")");
                    }
                  }
                }
              }));
    }

    if (isSuitableForClass(position)) {
      for (String s : ModifierChooser.getKeywords(position)) {
        result.consume(
            new OverrideableSpace(createKeyword(position, s), TailType.HUMBLE_SPACE_BEFORE_WORD));
      }
      result.consume(
          new OverrideableSpace(
              createKeyword(position, PsiKeyword.CLASS), TailType.HUMBLE_SPACE_BEFORE_WORD));
      if (PsiTreeUtil.getParentOfType(position, PsiCodeBlock.class, true, PsiMember.class)
          == null) {
        result.consume(
            new OverrideableSpace(
                createKeyword(position, PsiKeyword.INTERFACE), TailType.HUMBLE_SPACE_BEFORE_WORD));
        if (PsiUtil.getLanguageLevel(position).isAtLeast(LanguageLevel.JDK_1_5)) {
          result.consume(
              new OverrideableSpace(
                  createKeyword(position, PsiKeyword.ENUM), TailType.INSERT_SPACE));
        }
      }
    }

    addPrimitiveTypes(result, position);

    if (isAfterTypeDot(position)) {
      result.consume(createKeyword(position, PsiKeyword.CLASS));
    }

    addUnfinishedMethodTypeParameters(position, result);

    if (JavaMemberNameCompletionContributor.INSIDE_TYPE_PARAMS_PATTERN.accepts(position)) {
      result.consume(
          new OverrideableSpace(
              createKeyword(position, PsiKeyword.EXTENDS), TailType.HUMBLE_SPACE_BEFORE_WORD));
      result.consume(
          new OverrideableSpace(
              createKeyword(position, PsiKeyword.SUPER), TailType.HUMBLE_SPACE_BEFORE_WORD));
    }
  }
  private void reparse(
      String str, PsiElement element, final boolean isStaticImport, JavaClassReferenceSet context) {
    myElement = element;
    myContext = context;
    final List<JavaClassReference> referencesList = new ArrayList<JavaClassReference>();
    int currentDot = -1;
    int referenceIndex = 0;
    boolean allowDollarInNames = isAllowDollarInNames();
    boolean allowGenerics = false;
    boolean allowGenericsCalculated = false;
    boolean parsingClassNames = true;

    while (parsingClassNames) {
      int nextDotOrDollar = -1;
      for (int curIndex = currentDot + 1; curIndex < str.length(); ++curIndex) {
        final char ch = str.charAt(curIndex);

        if (ch == SEPARATOR || (ch == SEPARATOR2 && allowDollarInNames)) {
          nextDotOrDollar = curIndex;
          break;
        }

        if (((ch == SEPARATOR3 || ch == SEPARATOR4))) {
          if (!allowGenericsCalculated) {
            allowGenerics =
                !isStaticImport && PsiUtil.getLanguageLevel(element).hasEnumKeywordAndAutoboxing();
            allowGenericsCalculated = true;
          }

          if (allowGenerics) {
            nextDotOrDollar = curIndex;
            break;
          }
        }
      }

      if (nextDotOrDollar == -1) {
        nextDotOrDollar = currentDot + 1;
        for (int i = nextDotOrDollar;
            i < str.length() && Character.isJavaIdentifierPart(str.charAt(i));
            ++i) nextDotOrDollar++;
        parsingClassNames = false;
        int j = nextDotOrDollar;
        while (j < str.length() && Character.isWhitespace(str.charAt(j))) ++j;

        if (j < str.length()) {
          char ch = str.charAt(j);
          boolean recognized = false;

          if (ch == '[') {
            j++;
            while (j < str.length() && Character.isWhitespace(str.charAt(j))) ++j;

            if (j < str.length()) {
              ch = str.charAt(j);

              if (ch == ']') {
                j++;
                while (j < str.length() && Character.isWhitespace(str.charAt(j))) ++j;

                recognized = j == str.length();
              }
            }
          }

          final Boolean aBoolean = JavaClassReferenceProvider.JVM_FORMAT.getValue(getOptions());
          if (aBoolean == null || !aBoolean.booleanValue()) {
            if (!recognized)
              nextDotOrDollar = -1; // nonsensible characters anyway, don't do resolve
          }
        }
      }

      if (nextDotOrDollar != -1 && nextDotOrDollar < str.length()) {
        final char c = str.charAt(nextDotOrDollar);
        if (c == SEPARATOR3) {
          int end = str.lastIndexOf('>');
          if (end != -1 && end > nextDotOrDollar) {
            if (myNestedGenericParameterReferences == null)
              myNestedGenericParameterReferences = new ArrayList<JavaClassReferenceSet>(1);
            myNestedGenericParameterReferences.add(
                new JavaClassReferenceSet(
                    str.substring(nextDotOrDollar + 1, end),
                    myElement,
                    myStartInElement + nextDotOrDollar + 1,
                    isStaticImport,
                    myProvider,
                    this));
            parsingClassNames = false;
          } else {
            nextDotOrDollar = -1; // nonsensible characters anyway, don't do resolve
          }
        } else if (SEPARATOR4 == c && myContext != null) {
          if (myContext.myNestedGenericParameterReferences == null)
            myContext.myNestedGenericParameterReferences = new ArrayList<JavaClassReferenceSet>(1);
          myContext.myNestedGenericParameterReferences.add(
              new JavaClassReferenceSet(
                  str.substring(nextDotOrDollar + 1),
                  myElement,
                  myStartInElement + nextDotOrDollar + 1,
                  isStaticImport,
                  myProvider,
                  this));
          parsingClassNames = false;
        }
      }

      int beginIndex = currentDot + 1;
      while (beginIndex < nextDotOrDollar && Character.isWhitespace(str.charAt(beginIndex)))
        beginIndex++;

      final String subreferenceText =
          nextDotOrDollar > 0
              ? str.substring(beginIndex, nextDotOrDollar)
              : str.substring(beginIndex);

      TextRange textRange =
          new TextRange(
              myStartInElement + beginIndex,
              myStartInElement + (nextDotOrDollar > 0 ? nextDotOrDollar : str.length()));
      JavaClassReference currentContextRef =
          createReference(referenceIndex, subreferenceText, textRange, isStaticImport);
      referenceIndex++;
      referencesList.add(currentContextRef);
      if ((currentDot = nextDotOrDollar) < 0) {
        break;
      }
    }

    myReferences = referencesList.toArray(new JavaClassReference[referencesList.size()]);
  }
  public static boolean processDeclarations(
      @NotNull GrTypeDefinition grType,
      @NotNull PsiScopeProcessor processor,
      @NotNull ResolveState state,
      @Nullable PsiElement lastParent,
      @NotNull PsiElement place) {
    if (place instanceof GrCodeReferenceElement && lastParent instanceof GrModifierList) {
      final PsiElement possibleAnnotation =
          PsiTreeUtil.skipParentsOfType(place, GrCodeReferenceElement.class);
      if (possibleAnnotation instanceof GrAnnotation
          && possibleAnnotation.getParent() == lastParent) {
        return true; // don't process class members while resolving annotation which annotates
                     // current class
      }
    }

    for (final PsiTypeParameter typeParameter : grType.getTypeParameters()) {
      if (!processElement(processor, typeParameter, state)) return false;
    }

    NameHint nameHint = processor.getHint(NameHint.KEY);
    String name = nameHint == null ? null : nameHint.getName(state);
    ClassHint classHint = processor.getHint(ClassHint.KEY);
    final PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
    final PsiElementFactory factory = JavaPsiFacade.getElementFactory(place.getProject());

    boolean processInstanceMethods =
        (shouldProcessMethods(classHint) || shouldProcessProperties(classHint))
            && shouldProcessInstanceMembers(grType, lastParent);

    LanguageLevel level = PsiUtil.getLanguageLevel(place);
    if (shouldProcessProperties(classHint)) {
      Map<String, CandidateInfo> fieldsMap = CollectClassMembersUtil.getAllFields(grType);
      if (name != null) {
        CandidateInfo fieldInfo = fieldsMap.get(name);
        if (fieldInfo != null) {
          if (!processField(
              grType,
              processor,
              state,
              place,
              processInstanceMethods,
              substitutor,
              factory,
              level,
              fieldInfo)) {
            return false;
          }
        } else if (grType.isTrait() && lastParent != null) {
          PsiField field = findFieldByName(grType, name, false, true);
          if (field != null && field.hasModifierProperty(PsiModifier.PUBLIC)) {
            if (!processField(
                grType,
                processor,
                state,
                place,
                processInstanceMethods,
                substitutor,
                factory,
                level,
                new CandidateInfo(field, PsiSubstitutor.EMPTY))) {
              return false;
            }
          }
        }
      } else {
        for (CandidateInfo info : fieldsMap.values()) {
          if (!processField(
              grType,
              processor,
              state,
              place,
              processInstanceMethods,
              substitutor,
              factory,
              level,
              info)) {
            return false;
          }
        }
        if (grType.isTrait() && lastParent != null) {
          for (PsiField field : CollectClassMembersUtil.getFields(grType, true)) {
            if (field.hasModifierProperty(PsiModifier.PUBLIC)) {
              if (!processField(
                  grType,
                  processor,
                  state,
                  place,
                  processInstanceMethods,
                  substitutor,
                  factory,
                  level,
                  new CandidateInfo(field, PsiSubstitutor.EMPTY))) {
                return false;
              }
            }
          }
        }
      }
    }

    if (shouldProcessMethods(classHint)) {
      Map<String, List<CandidateInfo>> methodsMap =
          CollectClassMembersUtil.getAllMethods(grType, true);
      boolean isPlaceGroovy = place.getLanguage() == GroovyFileType.GROOVY_LANGUAGE;
      if (name == null) {
        for (List<CandidateInfo> list : methodsMap.values()) {
          for (CandidateInfo info : list) {
            if (!processMethod(
                grType,
                processor,
                state,
                place,
                processInstanceMethods,
                substitutor,
                factory,
                level,
                isPlaceGroovy,
                info)) {
              return false;
            }
          }
        }
      } else {
        List<CandidateInfo> byName = methodsMap.get(name);
        if (byName != null) {
          for (CandidateInfo info : byName) {
            if (!processMethod(
                grType,
                processor,
                state,
                place,
                processInstanceMethods,
                substitutor,
                factory,
                level,
                isPlaceGroovy,
                info)) {
              return false;
            }
          }
        }
      }
    }

    final GrTypeDefinitionBody body = grType.getBody();
    if (body != null) {
      if (shouldProcessClasses(classHint)) {
        for (PsiClass innerClass : getInnerClassesForResolve(grType, lastParent, place)) {
          final String innerClassName = innerClass.getName();
          if (nameHint != null && !innerClassName.equals(nameHint.getName(state))) {
            continue;
          }

          if (!processor.execute(innerClass, state)) {
            return false;
          }
        }
      }
    }

    return true;
  }
 @Override
 @NotNull
 public LanguageLevel getLanguageLevel() {
   return myLanguageLevel != null ? myLanguageLevel : PsiUtil.getLanguageLevel(myClass);
 }
 @Override
 @NotNull
 public LanguageLevel getLanguageLevel() {
   if (myLanguageLevel != null) return myLanguageLevel;
   return PsiUtil.getLanguageLevel(myClass);
 }
  @Override
  public Result acceptChar(char c, final int prefixLength, final Lookup lookup) {
    if (!lookup.getPsiFile().getLanguage().isKindOf(JavaLanguage.INSTANCE)) {
      return null;
    }

    LookupElement item = lookup.getCurrentItem();
    if (item == null) return null;

    final Object o = item.getObject();
    if (c == '!') {
      if (o instanceof PsiVariable) {
        if (PsiType.BOOLEAN.isAssignableFrom(((PsiVariable) o).getType()))
          return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
      }
      if (o instanceof PsiMethod) {
        final PsiType type = ((PsiMethod) o).getReturnType();
        if (type != null && PsiType.BOOLEAN.isAssignableFrom(type))
          return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
      }
      if (o instanceof PsiKeyword && ((PsiKeyword) o).textMatches(PsiKeyword.INSTANCEOF)) {
        return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
      }

      return null;
    }
    if (c == '.' && isWithinLiteral(lookup)) return Result.ADD_TO_PREFIX;

    if (c == ':') {
      PsiFile file = lookup.getPsiFile();
      PsiDocumentManager.getInstance(file.getProject())
          .commitDocument(lookup.getEditor().getDocument());
      PsiElement leaf = file.findElementAt(lookup.getEditor().getCaretModel().getOffset() - 1);
      if (PsiUtil.getLanguageLevel(file).isAtLeast(LanguageLevel.JDK_1_8)) {
        PsiStatement statement = PsiTreeUtil.getParentOfType(leaf, PsiStatement.class);
        if (statement == null
            || statement.getTextRange().getStartOffset()
                != leaf.getTextRange().getStartOffset()) { // not typing a statement label
          return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
        }
      }
      if (PsiTreeUtil.getParentOfType(leaf, PsiSwitchLabelStatement.class) != null
          || PsiTreeUtil.getParentOfType(leaf, PsiConditionalExpression.class) != null) {
        return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
      }
      return Result.HIDE_LOOKUP;
    }

    if (c == '[' || c == ']' || c == ')' || c == '>')
      return CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP;
    if (c == '<' && o instanceof PsiClass) return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
    if (c == '(') {
      if (o instanceof PsiClass) {
        if (PsiJavaPatterns.psiElement()
            .afterLeaf(PsiKeyword.NEW)
            .accepts(lookup.getPsiElement())) {
          return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
        }
        return Result.HIDE_LOOKUP;
      }
      if (o instanceof PsiType) {
        return Result.HIDE_LOOKUP;
      }
    }
    if ((c == ',' || c == '=') && o instanceof PsiVariable) {
      int lookupStart = lookup.getLookupStart();
      String name = ((PsiVariable) o).getName();
      if (lookupStart >= 0 && name != null && name.equals(lookup.itemPattern(item))) {
        return Result.HIDE_LOOKUP;
      }
    }

    if (c == '#'
        && PsiTreeUtil.getParentOfType(lookup.getPsiElement(), PsiDocComment.class) != null) {
      if (o instanceof PsiClass) {
        return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
      }
    }
    if (c == '(' && PsiKeyword.RETURN.equals(item.getLookupString())) {
      return Result.HIDE_LOOKUP;
    }
    return null;
  }