<commit_before>/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.codeInsight.completion;

import com.intellij.codeInsight.AutoPopupController;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.TailTypes;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupItem;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;

public class DefaultInsertHandler extends TemplateInsertHandler implements Cloneable {
  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.DefaultInsertHandler");

  public static final DefaultInsertHandler NO_TAIL_HANDLER = new DefaultInsertHandler(){
    @Override
    protected TailType getTailType(char completionChar, LookupItem item) {
      return TailType.NONE;
    }
  };

  public void handleInsert(final InsertionContext context, LookupElement item) {
    super.handleInsert(context, item);

    handleInsertInner(context, (LookupItem)item, context.getCompletionChar());
  }

  private void handleInsertInner(InsertionContext context, LookupItem item, final char completionChar) {
    final Project project = context.getProject();
    final Editor editor = context.getEditor();
    final Document document = editor.getDocument();
    PsiDocumentManager.getInstance(project).commitDocument(document);

    final PsiFile file = context.getFile();

    TailType tailType = getTailType(completionChar, item);

    InsertHandlerState state = new InsertHandlerState(context.getSelectionEndOffset(), context.getSelectionEndOffset());

    final boolean needLeftParenth = isToInsertParenth(context, item);
    final boolean hasParams = needLeftParenth && hasParams(context, item);

    if (CompletionUtil.isOverwrite(item, completionChar)) {
      removeEndOfIdentifier(needLeftParenth && hasParams, context);
    }
    else if(context.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET) != context.getSelectionEndOffset()) {
      JavaCompletionUtil.resetParensInfo(context.getOffsetMap());
    }

    handleParentheses(hasParams, needLeftParenth, tailType, context, state);
    handleBrackets(item, document, state);

    if (item.getObject() instanceof PsiVariable) {
      if (completionChar == '!' && PsiType.BOOLEAN.isAssignableFrom(((PsiVariable) item.getObject()).getType())) {
        PsiDocumentManager.getInstance(project).commitDocument(document);
        final PsiReferenceExpression ref =
            PsiTreeUtil.findElementOfClassAtOffset(file, state.tailOffset - 1, PsiReferenceExpression.class, false);
        if (ref != null) {
          FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EXCLAMATION_FINISH);
          document.insertString(ref.getTextRange().getStartOffset(), "!");
          state.caretOffset++;
          state.tailOffset++;
        }
      }
    }

    context.setTailOffset(state.tailOffset);
    state.caretOffset = processTail(tailType, state.caretOffset, state.tailOffset, editor);
    editor.getSelectionModel().removeSelection();

    qualifyIfNeeded(context, item);


    if (needLeftParenth && hasParams){
      // Invoke parameters popup
      AutoPopupController.getInstance(project).autoPopupParameterInfo(editor, null);
    }

    if (tailType == TailType.DOT){
      AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, null);
    }

    if (completionChar == '#') {
      context.setLaterRunnable(new Runnable() {
        public void run() {
           new CodeCompletionHandlerBase(CompletionType.BASIC).invoke(project, editor, file);
        }
      });
    }

    if (insertingAnnotation(context, item)) {
      // 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 @<commit_msg>don't popup member lookup after finishing a class name with dot<commit_after>/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.codeInsight.completion;

import com.intellij.codeInsight.AutoPopupController;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.TailTypes;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupItem;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;

public class DefaultInsertHandler extends TemplateInsertHandler implements Cloneable {
  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.DefaultInsertHandler");

  public static final DefaultInsertHandler NO_TAIL_HANDLER = new DefaultInsertHandler(){
    @Override
    protected TailType getTailType(char completionChar, LookupItem item) {
      return TailType.NONE;
    }
  };

  public void handleInsert(final InsertionContext context, LookupElement item) {
    super.handleInsert(context, item);

    handleInsertInner(context, (LookupItem)item, context.getCompletionChar());
  }

  private void handleInsertInner(InsertionContext context, LookupItem item, final char completionChar) {
    final Project project = context.getProject();
    final Editor editor = context.getEditor();
    final Document document = editor.getDocument();
    PsiDocumentManager.getInstance(project).commitDocument(document);

    final PsiFile file = context.getFile();

    TailType tailType = getTailType(completionChar, item);

    InsertHandlerState state = new InsertHandlerState(context.getSelectionEndOffset(), context.getSelectionEndOffset());

    final boolean needLeftParenth = isToInsertParenth(context, item);
    final boolean hasParams = needLeftParenth && hasParams(context, item);

    if (CompletionUtil.isOverwrite(item, completionChar)) {
      removeEndOfIdentifier(needLeftParenth && hasParams, context);
    }
    else if(context.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET) != context.getSelectionEndOffset()) {
      JavaCompletionUtil.resetParensInfo(context.getOffsetMap());
    }

    handleParentheses(hasParams, needLeftParenth, tailType, context, state);
    handleBrackets(item, document, state);

    if (item.getObject() instanceof PsiVariable) {
      if (completionChar == '!' && PsiType.BOOLEAN.isAssignableFrom(((PsiVariable) item.getObject()).getType())) {
        PsiDocumentManager.getInstance(project).commitDocument(document);
        final PsiReferenceExpression ref =
            PsiTreeUtil.findElementOfClassAtOffset(file, state.tailOffset - 1, PsiReferenceExpression.class, false);
        if (ref != null) {
          FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EXCLAMATION_FINISH);
          document.insertString(ref.getTextRange().getStartOffset(), "!");
          state.caretOffset++;
          state.tailOffset++;
        }
      }
    }

    context.setTailOffset(state.tailOffset);
    state.caretOffset = processTail(tailType, state.caretOffset, state.tailOffset, editor);
    editor.getSelectionModel().removeSelection();

    qualifyIfNeeded(context, item);


    if (needLeftParenth && hasParams){
      // Invoke parameters popup
      AutoPopupController.getInstance(project).autoPopupParameterInfo(editor, null);
    }

    if (tailType == TailType.DOT && !(item.getObject() instanceof PsiClass)) {
      AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, null);
    }

    if (completionChar == '#') {
      context.setLaterRunnable(new Runnable() {
        public void run() {
           new CodeCompletionHandlerBase(CompletionType.BASIC).invoke(project, editor, file);
        }
      });
    }

    if (insertingAnnotation(context, item)) {
      // 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 @
{'fraction_non_alphanumeric': 0.09646714259564342, 'fraction_numerical': 0.0023796448837635, 'mean_word_length': 4.64702842377261, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5566580', 'n_tokens_mistral': 3026, 'n_tokens_neox': 2946, 'n_words': 659}