private static void addBreakContinue(Consumer<LookupElement> result, PsiElement position) {
    PsiLoopStatement loop = PsiTreeUtil.getParentOfType(position, PsiLoopStatement.class);

    LookupElement br = createKeyword(position, PsiKeyword.BREAK);
    LookupElement cont = createKeyword(position, PsiKeyword.CONTINUE);
    TailType tailType;
    if (psiElement()
        .insideSequence(
            true,
            psiElement(PsiLabeledStatement.class),
            or(
                psiElement(PsiFile.class),
                psiElement(PsiMethod.class),
                psiElement(PsiClassInitializer.class)))
        .accepts(position)) {
      tailType = TailType.HUMBLE_SPACE_BEFORE_WORD;
    } else {
      tailType = TailType.SEMICOLON;
    }
    br = TailTypeDecorator.withTail(br, tailType);
    cont = TailTypeDecorator.withTail(cont, tailType);

    if (loop != null
        && new InsideElementFilter(new ClassFilter(PsiStatement.class))
            .isAcceptable(position, loop)) {
      result.consume(br);
      result.consume(cont);
    }
    if (psiElement().inside(PsiSwitchStatement.class).accepts(position)) {
      result.consume(br);
    }
  }
 @Override
 public void addCompletions(
     @NotNull final CompletionParameters parameters,
     final ProcessingContext context,
     @NotNull final CompletionResultSet result) {
   for (String[] stringArray :
       RegExpLanguageHosts.getInstance().getAllKnownProperties(parameters.getPosition())) {
     result.addElement(
         TailTypeDecorator.withTail(
             createLookupElement(stringArray[0], null, emptyIcon),
             TailType.createSimpleTailType('}')));
   }
 }
 @Override
 protected void addCompletions(
     @NotNull CompletionParameters parameters,
     ProcessingContext context,
     @NotNull CompletionResultSet result) {
   UnicodeCharacterNames.iterate(
       name -> {
         if (result.getPrefixMatcher().prefixMatches(name)) {
           final String type =
               new String(new int[] {UnicodeCharacterNames.getCodePoint(name)}, 0, 1);
           if (myEmbrace) {
             result.addElement(createLookupElement("{" + name + "}", type, emptyIcon));
           } else {
             result.addElement(
                 TailTypeDecorator.withTail(
                     createLookupElement(name, type, emptyIcon),
                     TailType.createSimpleTailType('}')));
           }
         }
         ProgressManager.checkCanceled();
       });
 }
  private static void fillExpectedTypeArgs(
      CompletionResultSet resultSet,
      PsiElement context,
      final PsiClass actualClass,
      final int index,
      PsiClassType.ClassResolveResult expectedType,
      TailType globalTail) {
    final PsiClass expectedClass = expectedType.getElement();

    if (!InheritanceUtil.isInheritorOrSelf(actualClass, expectedClass, true)) return;
    assert expectedClass != null;

    final PsiSubstitutor currentSubstitutor =
        TypeConversionUtil.getClassSubstitutor(expectedClass, actualClass, PsiSubstitutor.EMPTY);
    assert currentSubstitutor != null;

    PsiTypeParameter[] params = actualClass.getTypeParameters();
    final List<PsiTypeLookupItem> typeItems = new ArrayList<PsiTypeLookupItem>();
    for (int i = index; i < params.length; i++) {
      PsiType arg = getExpectedTypeArg(context, i, expectedType, currentSubstitutor, params);
      if (arg == null) {
        arg = getExpectedTypeArg(context, index, expectedType, currentSubstitutor, params);
        if (arg != null) {
          resultSet.addElement(
              TailTypeDecorator.withTail(
                  PsiTypeLookupItem.createLookupItem(arg, context),
                  getTail(index == params.length - 1)));
        }
        return;
      }
      typeItems.add(PsiTypeLookupItem.createLookupItem(arg, context));
    }

    resultSet.addElement(
        new TypeArgsLookupElement(
            typeItems,
            globalTail,
            ConstructorInsertHandler.hasConstructorParameters(actualClass, context)));
  }
  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));
    }
  }
 static void processLabelReference(CompletionResultSet result, PsiLabelReference ref) {
   for (String s : ref.getVariants()) {
     result.addElement(
         TailTypeDecorator.withTail(LookupElementBuilder.create(s), TailType.SEMICOLON));
   }
 }