private String getCaseCorrectedLookupString(LookupElement item) {
    String lookupString = item.getLookupString();
    if (item.isCaseSensitive()) {
      return lookupString;
    }

    final String prefix = itemPattern(item);
    final int length = prefix.length();
    if (length == 0 || !itemMatcher(item).prefixMatches(prefix)) return lookupString;
    boolean isAllLower = true;
    boolean isAllUpper = true;
    boolean sameCase = true;
    for (int i = 0; i < length && (isAllLower || isAllUpper || sameCase); i++) {
      final char c = prefix.charAt(i);
      boolean isLower = Character.isLowerCase(c);
      boolean isUpper = Character.isUpperCase(c);
      // do not take this kind of symbols into account ('_', '@', etc.)
      if (!isLower && !isUpper) continue;
      isAllLower = isAllLower && isLower;
      isAllUpper = isAllUpper && isUpper;
      sameCase = sameCase && isLower == Character.isLowerCase(lookupString.charAt(i));
    }
    if (sameCase) return lookupString;
    if (isAllLower) return lookupString.toLowerCase();
    if (isAllUpper) return StringUtil.toUpperCase(lookupString);
    return lookupString;
  }
  @Nullable
  private static AutoCompletionPolicy getAutocompletionPolicy(LookupElement element) {
    final AutoCompletionPolicy policy = AutoCompletionPolicy.getPolicy(element);
    if (policy != null) {
      return policy;
    }

    final LookupItem item = element.as(LookupItem.CLASS_CONDITION_KEY);
    if (item != null) {
      return item.getAutoCompletionPolicy();
    }

    return null;
  }
 private static void addCompletionChar(
     Project project,
     CompletionAssertions.WatchingInsertionContext context,
     LookupElement item,
     Editor editor,
     CompletionProgressIndicator indicator,
     char completionChar) {
   int tailOffset = context.getTailOffset();
   if (tailOffset < 0) {
     LOG.info(
         "tailOffset<0 after inserting "
             + item
             + " of "
             + item.getClass()
             + "; invalidated at: "
             + context.invalidateTrace
             + "\n--------");
   } else {
     editor.getCaretModel().moveToOffset(tailOffset);
   }
   if (context.getCompletionChar() == Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
     final Language language = PsiUtilBase.getLanguageInEditor(editor, project);
     if (language != null) {
       for (SmartEnterProcessor processor : SmartEnterProcessors.INSTANCE.forKey(language)) {
         if (processor.processAfterCompletion(editor, indicator.getParameters().getOriginalFile()))
           break;
       }
     }
   } else if (!editor
       .getCaretModel()
       .supportsMultipleCarets()) { // this will be done outside of runForEach caret context
     DataContext dataContext =
         DataManager.getInstance().getDataContext(editor.getContentComponent());
     EditorActionManager.getInstance()
         .getTypedAction()
         .getHandler()
         .execute(editor, completionChar, dataContext);
   }
 }
  private static CompletionAssertions.WatchingInsertionContext insertItem(
      final CompletionProgressIndicator indicator,
      final LookupElement item,
      final char completionChar,
      List<LookupElement> items,
      final CompletionLookupArranger.StatisticsUpdate update,
      final Editor editor,
      final PsiFile psiFile,
      final int caretOffset,
      final int idEndOffset) {
    editor.getCaretModel().moveToOffset(caretOffset);
    final int initialStartOffset = caretOffset - item.getLookupString().length();
    assert initialStartOffset >= 0
        : "negative startOffset: " + caretOffset + "; " + item.getLookupString();

    indicator
        .getOffsetMap()
        .addOffset(CompletionInitializationContext.START_OFFSET, initialStartOffset);
    indicator
        .getOffsetMap()
        .addOffset(CompletionInitializationContext.SELECTION_END_OFFSET, caretOffset);
    indicator
        .getOffsetMap()
        .addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, idEndOffset);

    final CompletionAssertions.WatchingInsertionContext context =
        new CompletionAssertions.WatchingInsertionContext(
            indicator.getOffsetMap(), psiFile, completionChar, items, editor);
    ApplicationManager.getApplication()
        .runWriteAction(
            new Runnable() {
              @Override
              public void run() {
                if (caretOffset != idEndOffset && completionChar == Lookup.REPLACE_SELECT_CHAR) {
                  editor.getDocument().deleteString(caretOffset, idEndOffset);
                }

                assert context.getStartOffset() >= 0
                    : "stale startOffset: was "
                        + initialStartOffset
                        + "; selEnd="
                        + caretOffset
                        + "; idEnd="
                        + idEndOffset
                        + "; file="
                        + context.getFile();
                assert context.getTailOffset() >= 0
                    : "stale tail: was "
                        + initialStartOffset
                        + "; selEnd="
                        + caretOffset
                        + "; idEnd="
                        + idEndOffset
                        + "; file="
                        + context.getFile();

                item.handleInsert(context);
                Project project = indicator.getProject();
                PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();

                if (context.shouldAddCompletionChar()) {
                  addCompletionChar(project, context, item, editor, indicator, completionChar);
                }
                if (!editor
                    .getCaretModel()
                    .supportsMultipleCarets()) { // done later, outside of this method
                  context.stopWatching();
                }
                editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
              }
            });
    update.addSparedChars(indicator, item, context, completionChar);
    return context;
  }
  public void finishLookup(char completionChar, @Nullable final LookupElement item) {
    //noinspection deprecation,unchecked
    if (item == null
        || item instanceof EmptyLookupItem
        || item.getObject() instanceof DeferredUserLookupValue
            && item.as(LookupItem.CLASS_CONDITION_KEY) != null
            && !((DeferredUserLookupValue) item.getObject())
                .handleUserSelection(item.as(LookupItem.CLASS_CONDITION_KEY), myProject)) {
      doHide(false, true);
      fireItemSelected(null, completionChar);
      return;
    }

    if (myDisposed) { // DeferredUserLookupValue could close us in any way
      return;
    }

    final PsiFile file = getPsiFile();
    boolean writableOk =
        file == null || FileModificationService.getInstance().prepareFileForWrite(file);
    if (myDisposed) { // ensureFilesWritable could close us by showing a dialog
      return;
    }

    if (!writableOk) {
      doHide(false, true);
      fireItemSelected(null, completionChar);
      return;
    }

    final String prefix = itemPattern(item);
    boolean plainMatch =
        ContainerUtil.or(
            item.getAllLookupStrings(),
            new Condition<String>() {
              @Override
              public boolean value(String s) {
                return StringUtil.containsIgnoreCase(s, prefix);
              }
            });
    if (!plainMatch) {
      FeatureUsageTracker.getInstance()
          .triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_CAMEL_HUMPS);
    }

    myFinishing = true;
    ApplicationManager.getApplication()
        .runWriteAction(
            new Runnable() {
              public void run() {
                myEditor.getDocument().startGuardedBlockChecking();
                try {
                  insertLookupString(item, getPrefixLength(item));
                } finally {
                  myEditor.getDocument().stopGuardedBlockChecking();
                }
              }
            });

    if (myDisposed) { // any document listeners could close us
      return;
    }

    doHide(false, true);

    fireItemSelected(item, completionChar);
  }
 private static LookupElementPresentation renderItemApproximately(LookupElement item) {
   final LookupElementPresentation p = new LookupElementPresentation();
   item.renderElement(p);
   return p;
 }