summaryrefslogtreecommitdiffstats
path: root/integration
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@gmail.com>2022-02-16 18:33:44 +0100
committerJon Bratseth <bratseth@gmail.com>2022-02-16 18:33:44 +0100
commit524cd03d4c8a175d1ab91e32ef393494e73e6ab7 (patch)
tree3dec0918565b8b2c4f8e39437aba6446f19d4b13 /integration
parentd0f3ca517d00656f1b4ebcacab715432855e751f (diff)
Find usages across filers and in lexical scope
Diffstat (limited to 'integration')
-rw-r--r--integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/SdFindUsagesHandler.java40
-rw-r--r--integration/intellij/src/test/java/ai/vespa/intellij/PluginTestBase.java5
-rw-r--r--integration/intellij/src/test/java/ai/vespa/intellij/findUsages/FindUsagesTest.java31
-rw-r--r--integration/intellij/src/test/java/ai/vespa/intellij/model/SchemaTest.java1
-rw-r--r--integration/intellij/src/test/java/ai/vespa/intellij/model/TestProjectDescriptor.java14
5 files changed, 44 insertions, 47 deletions
diff --git a/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/SdFindUsagesHandler.java b/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/SdFindUsagesHandler.java
index 4af276c26df..ebe21161667 100644
--- a/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/SdFindUsagesHandler.java
+++ b/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/SdFindUsagesHandler.java
@@ -13,7 +13,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.usageView.UsageInfo;
@@ -27,6 +26,7 @@ import java.util.List;
* This class handles creating the "Find Usages" window.
*
* @author Shahar Ariel
+ * @author bratseth
*/
public class SdFindUsagesHandler extends FindUsagesHandler {
@@ -38,42 +38,54 @@ public class SdFindUsagesHandler extends FindUsagesHandler {
public boolean processElementUsages(PsiElement elementToSearch,
Processor<? super UsageInfo> processor,
FindUsagesOptions options) {
- SearchScope scope = options.searchScope;
- boolean searchText = options.isSearchForTextOccurrences && scope instanceof GlobalSearchScope;
-
if (options.isUsages) {
if (elementToSearch instanceof SdFunctionDefinition) {
findFunctionUsages((SdFunctionDefinition) elementToSearch, processor);
} else {
boolean success =
- ReferencesSearch.search(createSearchParameters(elementToSearch, scope, options))
+ ReferencesSearch.search(createSearchParameters(elementToSearch, options.searchScope, options))
.forEach((PsiReference ref) -> processor.process(new UsageInfo(ref)));
if (!success) return false;
}
}
- if (searchText) {
+ if (options.isSearchForTextOccurrences && options.searchScope instanceof GlobalSearchScope) {
if (options.fastTrack != null)
- options.fastTrack.searchCustom(consumer -> processUsagesInText(elementToSearch, processor, (GlobalSearchScope)scope));
+ options.fastTrack.searchCustom(consumer -> processUsagesInText(elementToSearch,
+ processor,
+ (GlobalSearchScope)options.searchScope));
else
- return processUsagesInText(elementToSearch, processor, (GlobalSearchScope)scope);
+ return processUsagesInText(elementToSearch, processor, (GlobalSearchScope)options.searchScope);
}
return true;
}
+ /**
+ * Finds usages brute force. There is built-in search functionality in the IntelliJ SDK but I could
+ * not make it work across files. Since the lexical, scope of a rank profile will be quite small
+ * brute force might be faster in any case.
+ *
+ * Since search is done by a separate thread it cannot safely access the Psi tree.
+ * This splits Psi tree accesses into smaller chunks which are handed off to the Reader
+ * on the assumption that this keeps the IDE responsive. I have not found documentation
+ * on that.
+ */
private void findFunctionUsages(SdFunctionDefinition functionToFind, Processor<? super UsageInfo> processor) {
String functionNameToFind = ReadAction.compute(functionToFind::getName);
+ Schema schema = ReadAction.compute(this::resolveSchema);
+ var rankProfile = ReadAction.compute(() -> schema.rankProfiles()
+ .get(PsiTreeUtil.getParentOfType(functionToFind, SdRankProfileDefinition.class).getName()));
+ findFunctionUsages(functionNameToFind, functionToFind, rankProfile, processor);
+ }
+
+ private Schema resolveSchema() {
PsiFile file = getPsiElement().getContainingFile();
- var rankProfileDefinition = PsiTreeUtil.getParentOfType(functionToFind, SdRankProfileDefinition.class);
- Schema schema;
if (file.getVirtualFile().getPath().endsWith(".profile")) {
Path schemaFile = Path.fromString(file.getVirtualFile().getParent().getPath() + ".sd");
- schema = ReadAction.compute(() -> Schema.fromProjectFile(getProject(), schemaFile));
+ return ReadAction.compute(() -> Schema.fromProjectFile(getProject(), schemaFile));
}
else { // schema
- schema = ReadAction.compute(() -> Schema.fromProjectFile(getProject(), Path.fromString(file.getVirtualFile().getPath())));
+ return ReadAction.compute(() -> Schema.fromProjectFile(getProject(), Path.fromString(file.getVirtualFile().getPath())));
}
- var rankProfile = ReadAction.compute(() -> schema.rankProfiles().get(rankProfileDefinition.getName()));
- findFunctionUsages(functionNameToFind, functionToFind, rankProfile, processor);
}
private void findFunctionUsages(String functionNameToFind,
diff --git a/integration/intellij/src/test/java/ai/vespa/intellij/PluginTestBase.java b/integration/intellij/src/test/java/ai/vespa/intellij/PluginTestBase.java
index 1ba2dcf2785..699f4ebab42 100644
--- a/integration/intellij/src/test/java/ai/vespa/intellij/PluginTestBase.java
+++ b/integration/intellij/src/test/java/ai/vespa/intellij/PluginTestBase.java
@@ -1,7 +1,6 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package ai.vespa.intellij;
-import ai.vespa.intellij.model.TestProjectDescriptor;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import org.junit.Test;
@@ -36,4 +35,8 @@ public class PluginTestBase extends LightJavaCodeInsightFixtureTestCase {
@Test
public void testDummy() {}
+ static class TestProjectDescriptor extends LightProjectDescriptor {
+
+ }
+
}
diff --git a/integration/intellij/src/test/java/ai/vespa/intellij/findUsages/FindUsagesTest.java b/integration/intellij/src/test/java/ai/vespa/intellij/findUsages/FindUsagesTest.java
index c0ddb79606b..fd21e7ec4ad 100644
--- a/integration/intellij/src/test/java/ai/vespa/intellij/findUsages/FindUsagesTest.java
+++ b/integration/intellij/src/test/java/ai/vespa/intellij/findUsages/FindUsagesTest.java
@@ -2,7 +2,6 @@
package ai.vespa.intellij.findUsages;
import ai.vespa.intellij.PluginTestBase;
-import ai.vespa.intellij.schema.SdUtil;
import ai.vespa.intellij.schema.findUsages.SdFindUsagesHandler;
import ai.vespa.intellij.schema.model.Schema;
import ai.vespa.intellij.schema.utils.Path;
@@ -21,19 +20,6 @@ import java.util.List;
public class FindUsagesTest extends PluginTestBase {
@Test
- public void testTmp() {
- useDir("src/test/applications/rankprofilemodularity");
- var tester = new UsagesTester("test.sd", getProject());
- tester.assertFunctionUsages("3 references in parent schema", 3, "outside_schema2", "fo2");
- }
-
- @Test
- public void testTmp2() {
- useDir("src/test/applications/rankprofilemodularity");
- var tester = new UsagesTester("test.sd", getProject());
- }
-
- @Test
public void testFindUsages() {
useDir("src/test/applications/rankprofilemodularity");
var tester = new UsagesTester("test.sd", getProject());
@@ -41,16 +27,26 @@ public class FindUsagesTest extends PluginTestBase {
tester.assertFunctionUsages("1 local ref in first-phase", 1, "in_schema2", "f2");
tester.assertFunctionUsages("2 local refs", 2, "in_schema2", "ff1");
tester.assertFunctionUsages("1 local ref", 1, "in_schema4", "f2");
- tester.assertFunctionUsages("1 local refa", 1, "outside_schema1", "local1");
+ tester.assertFunctionUsages("1 local ref", 1, "outside_schema1", "local1");
tester.assertFunctionUsages("4 local refs", 4, "outside_schema1", "local2");
tester.assertFunctionUsages("3 refs in parent schema", 3, "outside_schema2", "fo2");
}
+ @Test
+ public void testUsageDetails() {
+ useDir("src/test/applications/rankprofilemodularity");
+ var tester = new UsagesTester("test.sd", getProject());
+ UsageInfo usage = tester.assertFunctionUsages("1 local ref", 1, "outside_schema1", "local1").get(0);
+ assertEquals(93, usage.getNavigationOffset());
+ assertEquals(93 + 6, usage.getNavigationRange().getEndOffset());
+ }
+
private static class UsagesTester {
final Project project;
final Schema schema;
final SdFindUsagesHandler handler;
+ final MockUsageProcessor usageProcessor = new MockUsageProcessor();
UsagesTester(String schemaName, Project project) {
this.project = project;
@@ -58,13 +54,14 @@ public class FindUsagesTest extends PluginTestBase {
this.handler = new SdFindUsagesHandler(schema.definition());
}
- void assertFunctionUsages(String explanation, int expectedUsages, String profileName, String functionName) {
+ List<UsageInfo> assertFunctionUsages(String explanation, int expectedUsages, String profileName, String functionName) {
var function = schema.rankProfiles().get(profileName).definedFunctions().get(functionName).get(0).definition();
- var usageProcessor = new MockUsageProcessor();
var options = new FindUsagesOptions(project);
+ usageProcessor.usages.clear();
options.isUsages = true;
handler.processElementUsages(function, usageProcessor, options);
assertEquals(explanation, expectedUsages, usageProcessor.usages.size());
+ return usageProcessor.usages;
}
}
diff --git a/integration/intellij/src/test/java/ai/vespa/intellij/model/SchemaTest.java b/integration/intellij/src/test/java/ai/vespa/intellij/model/SchemaTest.java
index fb71e701411..9cf10cdffa2 100644
--- a/integration/intellij/src/test/java/ai/vespa/intellij/model/SchemaTest.java
+++ b/integration/intellij/src/test/java/ai/vespa/intellij/model/SchemaTest.java
@@ -51,7 +51,6 @@ public class SchemaTest extends PluginTestBase {
assertEquals(2, profile.inherited().size());
assertEquals("outside_schema1", profile.inherited().get("outside_schema1").name());
assertEquals("outside_schema2", profile.inherited().get("outside_schema2").name());
- schema.functions().entrySet().stream().forEach(e -> System.out.println(e));
assertEquals("8 proper functions + first-phase", 9, schema.functions().size());
assertEquals(schema.rankProfiles().get("in_schema2").definedFunctions().get("ff1"),
schema.functions().get("ff1"));
diff --git a/integration/intellij/src/test/java/ai/vespa/intellij/model/TestProjectDescriptor.java b/integration/intellij/src/test/java/ai/vespa/intellij/model/TestProjectDescriptor.java
deleted file mode 100644
index 5952b17a642..00000000000
--- a/integration/intellij/src/test/java/ai/vespa/intellij/model/TestProjectDescriptor.java
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package ai.vespa.intellij.model;
-
-import com.intellij.testFramework.LightProjectDescriptor;
-
-/**
- * Describes a project used in unit tests.
- * https://plugins.jetbrains.com/docs/intellij/light-and-heavy-tests.html
- *
- * @author bratseth
- */
-public class TestProjectDescriptor extends LightProjectDescriptor {
-
-}