<commit_before>package com.intellij.codeInsight.navigation.actions;

import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.codeInsight.actions.BaseCodeInsightAction;
import com.intellij.codeInsight.navigation.NavigationUtil;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.ide.util.EditSourceUtil;
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.pom.Navigatable;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.util.PsiUtilBase;
import org.jetbrains.annotations.Nullable;

import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;

public class GotoDeclarationAction extends BaseCodeInsightAction implements CodeInsightActionHandler {
  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.navigation.actions.GotoDeclarationAction");
  protected CodeInsightActionHandler getHandler() {
    return this;
  }

  protected boolean isValidForFile(Project project, Editor editor, final PsiFile file) {
    return true;
  }

  protected boolean isValidForLookup() {
    return true;
  }

  public void invoke(final Project project, Editor editor, PsiFile file) {
    PsiDocumentManager.getInstance(project).commitAllDocuments();

    PsiElement element;
    try {
      int offset = editor.getCaretModel().getOffset();
      element = findTargetElement(project, editor, offset);
      if (element == null) {
        FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.goto.declaration");
        chooseAmbiguousTarget(editor, offset);
        return;
      }
    }
    finally {
      DumbService.getInstance(project).showDumbModeNotification("Navigation is not available here during index update");
    }

    FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.goto.declaration");
    PsiElement navElement = element.getNavigationElement();

    navElement = TargetElementUtilBase.getInstance().getGotoDeclarationTarget(element, navElement);

    if (navElement instanceof Navigatable) {
      if (((Navigatable)navElement).canNavigate()) {
        ((Navigatable)navElement).navigate(true);
      }
    }
    else if (navElement != null) {
      int navOffset = navElement.getTextOffset();
      VirtualFile virtualFile = PsiUtilBase.getVirtualFile(navElement);
      if (virtualFile != null) {
        new OpenFileDescriptor(project, virtualFile, navOffset).navigate(true);
      }
    }
  }

  private static void chooseAmbiguousTarget(final Editor editor, int offset) {
    PsiElementProcessor<PsiElement> navigateProcessor = new PsiElementProcessor<PsiElement>() {
      public boolean execute(final PsiElement element) {
        Navigatable navigatable = EditSourceUtil.getDescriptor(element);
        if (navigatable != null && navigatable.canNavigate()) {
          navigatable.navigate(true);
        }
        return true;
      }
    };
    chooseAmbiguousTarget(editor, offset,navigateProcessor, CodeInsightBundle.message("declaration.navigation.title"));
  }

  // returns true if processor is run or is going to be run after showing popup
  public static boolean chooseAmbiguousTarget(final Editor editor, int offset, PsiElementProcessor<PsiElement> processor,
                                              String titlePattern) {
    if (TargetElementUtilBase.inVirtualSpace(editor, offset)) {
      return false;
    }

    final PsiReference reference = TargetElementUtilBase.findReference(editor, offset);
    final Collection<PsiElement> candidates = suggestCandidates(reference);
    if (candidates.size() == 1) {
      PsiElement element = candidates.iterator().next();
      LOG.assertTrue(element != null);
      processor.execute(element);
      return true;
    }
    else if (candidates.size() > 1) {
      PsiElement[] elements = candidates.toArray(new PsiElement[candidates.size()]);
      final TextRange range = reference.getRangeInElement();
      final String refText = range.substring(reference.getElement().getText());
      String title = MessageFormat.format(titlePattern, refText);
      NavigationUtil.getPsiElementPopup(elements, new DefaultPsiElementCellRenderer(), title, processor).showInBestPositionFor(editor);
      return true;
    }
    return false;
  }

  static Collection<PsiElement> suggestCandidates(final PsiReference reference) {
    if (reference == null) {
      return Collections.emptyList();
    }
    return TargetElementUtilBase.getInstance().getTargetCandidates(reference);
  }

  public boolean startInWriteAction() {
    return false;
  }

  @Nullable
  public static PsiElement findTargetElement(Project project, Editor editor, int offset) {
    if (TargetElementUtilBase.inVirtualSpace(editor, offset)) {
      return null;
    }

    PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
    if (file == null) {
      return null;
    }
    PsiElement elementAt = file.findElementAt(offset);

    for (GotoDeclarationHandler handler : Extensions.getExtensions(GotoDeclarationHandler.EP_NAME)) {
      PsiElement result = handler.getGotoDeclarationTarget(elementAt);
      if (result != null) {
        return result;
      }
    }

    int flags = TargetElementUtilBase.getInstance().getAllAccepted() & ~TargetElementUtilBase.ELEMENT_NAME_ACCEPTED;
    return TargetElementUtilBase.getInstance().findTargetElement(editor, flags, offset);
  }
}
<commit_msg>show goto declaration dumb mode notification, second attempt<commit_after>package com.intellij.codeInsight.navigation.actions;

import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.codeInsight.actions.BaseCodeInsightAction;
import com.intellij.codeInsight.navigation.NavigationUtil;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.ide.util.EditSourceUtil;
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.pom.Navigatable;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.util.PsiUtilBase;
import org.jetbrains.annotations.Nullable;

import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;

public class GotoDeclarationAction extends BaseCodeInsightAction implements CodeInsightActionHandler {
  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.navigation.actions.GotoDeclarationAction");
  protected CodeInsightActionHandler getHandler() {
    return this;
  }

  protected boolean isValidForFile(Project project, Editor editor, final PsiFile file) {
    return true;
  }

  protected boolean isValidForLookup() {
    return true;
  }

  public void invoke(final Project project, Editor editor, PsiFile file) {
    PsiDocumentManager.getInstance(project).commitAllDocuments();

    PsiElement element;
    try {
      int offset = editor.getCaretModel().getOffset();
      element = findTargetElement(project, editor, offset);
      if (element == null) {
        FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.goto.declaration");
        chooseAmbiguousTarget(editor, offset);
        return;
      }
    }
    catch (IndexNotReadyException e) {
      DumbService.getInstance(project).showDumbModeNotification("Navigation is not available here during index update");
      return;
    }

    FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.goto.declaration");
    PsiElement navElement = element.getNavigationElement();

    navElement = TargetElementUtilBase.getInstance().getGotoDeclarationTarget(element, navElement);

    if (navElement instanceof Navigatable) {
      if (((Navigatable)navElement).canNavigate()) {
        ((Navigatable)navElement).navigate(true);
      }
    }
    else if (navElement != null) {
      int navOffset = navElement.getTextOffset();
      VirtualFile virtualFile = PsiUtilBase.getVirtualFile(navElement);
      if (virtualFile != null) {
        new OpenFileDescriptor(project, virtualFile, navOffset).navigate(true);
      }
    }
  }

  private static void chooseAmbiguousTarget(final Editor editor, int offset) {
    PsiElementProcessor<PsiElement> navigateProcessor = new PsiElementProcessor<PsiElement>() {
      public boolean execute(final PsiElement element) {
        Navigatable navigatable = EditSourceUtil.getDescriptor(element);
        if (navigatable != null && navigatable.canNavigate()) {
          navigatable.navigate(true);
        }
        return true;
      }
    };
    chooseAmbiguousTarget(editor, offset,navigateProcessor, CodeInsightBundle.message("declaration.navigation.title"));
  }

  // returns true if processor is run or is going to be run after showing popup
  public static boolean chooseAmbiguousTarget(final Editor editor, int offset, PsiElementProcessor<PsiElement> processor,
                                              String titlePattern) {
    if (TargetElementUtilBase.inVirtualSpace(editor, offset)) {
      return false;
    }

    final PsiReference reference = TargetElementUtilBase.findReference(editor, offset);
    final Collection<PsiElement> candidates = suggestCandidates(reference);
    if (candidates.size() == 1) {
      PsiElement element = candidates.iterator().next();
      LOG.assertTrue(element != null);
      processor.execute(element);
      return true;
    }
    else if (candidates.size() > 1) {
      PsiElement[] elements = candidates.toArray(new PsiElement[candidates.size()]);
      final TextRange range = reference.getRangeInElement();
      final String refText = range.substring(reference.getElement().getText());
      String title = MessageFormat.format(titlePattern, refText);
      NavigationUtil.getPsiElementPopup(elements, new DefaultPsiElementCellRenderer(), title, processor).showInBestPositionFor(editor);
      return true;
    }
    return false;
  }

  static Collection<PsiElement> suggestCandidates(final PsiReference reference) {
    if (reference == null) {
      return Collections.emptyList();
    }
    return TargetElementUtilBase.getInstance().getTargetCandidates(reference);
  }

  public boolean startInWriteAction() {
    return false;
  }

  @Nullable
  public static PsiElement findTargetElement(Project project, Editor editor, int offset) {
    if (TargetElementUtilBase.inVirtualSpace(editor, offset)) {
      return null;
    }

    PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
    if (file == null) {
      return null;
    }
    PsiElement elementAt = file.findElementAt(offset);

    for (GotoDeclarationHandler handler : Extensions.getExtensions(GotoDeclarationHandler.EP_NAME)) {
      PsiElement result = handler.getGotoDeclarationTarget(elementAt);
      if (result != null) {
        return result;
      }
    }

    int flags = TargetElementUtilBase.getInstance().getAllAccepted() & ~TargetElementUtilBase.ELEMENT_NAME_ACCEPTED;
    return TargetElementUtilBase.getInstance().findTargetElement(editor, flags, offset);
  }
}

{'fraction_non_alphanumeric': 0.09440675161343703, 'fraction_numerical': 0.00033096144299189144, 'mean_word_length': 4.360088691796009, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4944159', 'n_tokens_mistral': 3302, 'n_tokens_neox': 3228, 'n_words': 662}