From 1200518d1299b5d3073566eb9f36dfd35eea192d Mon Sep 17 00:00:00 2001 From: Scott Wells Date: Tue, 17 Dec 2024 13:25:43 -0600 Subject: [PATCH] Issue 708 - Fresh branch due to merge conflicts. --- .../usages/LSPExternalReferencesFinder.java | 32 +++++++++++++---- .../lsp4ij/usages/LSPUsageSearcher.java | 34 +++++++++++++++---- 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPExternalReferencesFinder.java b/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPExternalReferencesFinder.java index 5766d361f..8561f2176 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPExternalReferencesFinder.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPExternalReferencesFinder.java @@ -26,6 +26,7 @@ import com.intellij.psi.PsiReference; import com.intellij.psi.impl.source.resolve.reference.PsiReferenceUtil; import com.intellij.psi.search.PsiSearchHelper; +import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.UsageSearchContext; import com.intellij.util.Processor; import com.redhat.devtools.lsp4ij.LSPIJUtils; @@ -48,25 +49,41 @@ private LSPExternalReferencesFinder() { /** * Processes all external references for the LSP4IJ element at the offset in the specified file. * - * @param file the file for which the element at the specified offset should be processed for external references - * @param offset the offset of the element in the file - * @param processor the external reference processor + * @param file the file for which the element at the specified offset should be processed for external references + * @param offset the offset of the element in the file + * @param processor the external reference processor */ public static void processExternalReferences(@NotNull PsiFile file, int offset, @NotNull Processor processor) { + processExternalReferences(file, offset, ReadAction.compute(file::getUseScope), processor); + } + + /** + * Processes all external references for the LSP4IJ element at the offset in the specified file. + * + * @param file the file for which the element at the specified offset should be processed for external references + * @param offset the offset of the element in the file + * @param searchScope the search scope + * @param processor the external reference processor + */ + public static void processExternalReferences(@NotNull PsiFile file, + int offset, + @NotNull SearchScope searchScope, + @NotNull Processor processor) { VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile != null) { Document document = LSPIJUtils.getDocument(virtualFile); TextRange wordTextRange = document != null ? LSPIJUtils.getWordRangeAt(document, file, offset) : null; if (wordTextRange != null) { LSPPsiElement wordElement = new LSPPsiElement(file, wordTextRange); - String wordText = wordElement.getText(); + String wordText = ReadAction.compute(wordElement::getText); if (StringUtil.isNotEmpty(wordText)) { processExternalReferences( file, wordText, wordTextRange, + searchScope, ProgressManager.getInstance().getProgressIndicator(), processor ); @@ -78,6 +95,7 @@ public static void processExternalReferences(@NotNull PsiFile file, private static void processExternalReferences(@NotNull PsiFile file, @NotNull String wordText, @NotNull TextRange wordTextRange, + @NotNull SearchScope searchScope, @Nullable ProgressIndicator progressIndicator, @NotNull Processor processor) { VirtualFile virtualFile = file.getVirtualFile(); @@ -95,7 +113,7 @@ private static void processExternalReferences(@NotNull PsiFile file, } Set externalReferenceKeys = new HashSet<>(); - PsiSearchHelper.getInstance(project).processElementsWithWord( + ReadAction.run(() -> PsiSearchHelper.getInstance(project).processElementsWithWord( (element, offsetInElement) -> { PsiReference originalReference = element.findReferenceAt(offsetInElement); List references = originalReference != null ? @@ -132,11 +150,11 @@ private static void processExternalReferences(@NotNull PsiFile file, } return true; }, - ReadAction.compute(file::getUseScope), + searchScope, wordText, UsageSearchContext.ANY, caseSensitive - ); + )); } @Nullable diff --git a/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPUsageSearcher.java b/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPUsageSearcher.java index 0aae7dd74..8e569a24f 100644 --- a/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPUsageSearcher.java +++ b/src/main/java/com/redhat/devtools/lsp4ij/usages/LSPUsageSearcher.java @@ -16,6 +16,7 @@ import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.editor.Document; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -24,6 +25,7 @@ import com.intellij.usages.UsageInfo2UsageAdapter; import com.intellij.util.Processor; import com.redhat.devtools.lsp4ij.LSPIJUtils; +import com.redhat.devtools.lsp4ij.LanguageServiceAccessor; import org.eclipse.lsp4j.Position; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -53,11 +55,30 @@ public class LSPUsageSearcher extends CustomUsageSearcher { @Override public void processElementUsages(@NotNull PsiElement element, @NotNull Processor processor, @NotNull FindUsagesOptions options) { + + PsiFile file = element.getContainingFile(); + if (file == null) { + return; + } + + VirtualFile virtualFile = file.getVirtualFile(); + if (virtualFile == null) { + return; + } + + Project project = element.getProject(); + if (!LanguageServiceAccessor.getInstance(project).hasAny( + virtualFile, + l -> l.getClientFeatures().getUsageFeature().isSupported(file) + )) { + return; + } + if (element instanceof LSPUsageTriggeredPsiElement elt) { if (elt.getLSPReferences() != null) { elt.getLSPReferences() .forEach(ref -> { - var psiElement = LSPUsagesManager.toPsiElement(ref.location(), ref.languageServer().getClientFeatures(), LSPUsagePsiElement.UsageKind.references, element.getProject()); + var psiElement = LSPUsagesManager.toPsiElement(ref.location(), ref.languageServer().getClientFeatures(), LSPUsagePsiElement.UsageKind.references, project); if (psiElement != null) { processor.process(ReadAction.compute(() -> new UsageInfo2UsageAdapter(new UsageInfo(psiElement)))); } @@ -66,10 +87,6 @@ public void processElementUsages(@NotNull PsiElement element, @NotNull Processor } } - PsiFile file = element.getContainingFile(); - if (file == null) { - return; - } // Get position where the "Find Usages" has been triggered Position position = getPosition(element, file); if (position == null) { @@ -98,7 +115,12 @@ public void processElementUsages(@NotNull PsiElement element, @NotNull Processor } // For completeness' sake, also collect external usages to LSP (pseudo-)elements - LSPExternalReferencesFinder.processExternalReferences(file, element.getTextOffset(), reference -> processor.process(new UsageInfo2UsageAdapter(new UsageInfo(reference)))); + LSPExternalReferencesFinder.processExternalReferences( + file, + ReadAction.compute(element::getTextOffset), + options.searchScope, + reference -> processor.process(ReadAction.compute(() -> new UsageInfo2UsageAdapter(new UsageInfo(reference)))) + ); } @Nullable