aboutsummaryrefslogtreecommitdiffstats
path: root/integration
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@gmail.com>2022-02-17 13:19:26 +0100
committerJon Bratseth <bratseth@gmail.com>2022-02-17 13:19:26 +0100
commit55557bfbc0e0d794dd220ac1f6cc4e3a9f5e9bcf (patch)
tree3adf3f3982aed916c98e3dc477f39c75f2b7ab9c /integration
parent88dd3b6dfefc5100d4582abdfb1088382ff76156 (diff)
Goto definition
Diffstat (limited to 'integration')
-rw-r--r--integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/FunctionDefinitionFinder.java60
-rw-r--r--integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/FunctionUsageFinder.java40
-rw-r--r--integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/SdFindUsagesHandler.java7
-rw-r--r--integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/UsageFinder.java43
-rw-r--r--integration/intellij/src/test/java/ai/vespa/intellij/findUsages/FindDefinitionTest.java24
-rw-r--r--integration/intellij/src/test/java/ai/vespa/intellij/findUsages/FindUsagesTest.java37
-rw-r--r--integration/intellij/src/test/java/ai/vespa/intellij/findUsages/UsagesTester.java67
7 files changed, 208 insertions, 70 deletions
diff --git a/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/FunctionDefinitionFinder.java b/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/FunctionDefinitionFinder.java
new file mode 100644
index 00000000000..7d8aafc8f8b
--- /dev/null
+++ b/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/FunctionDefinitionFinder.java
@@ -0,0 +1,60 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package ai.vespa.intellij.schema.findUsages;
+
+import ai.vespa.intellij.schema.model.RankProfile;
+import ai.vespa.intellij.schema.model.Schema;
+import ai.vespa.intellij.schema.psi.SdRankProfileDefinition;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.progress.ProgressIndicatorProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.util.Processor;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Finds the definition of a function.
+ *
+ * @author bratseth
+ */
+public class FunctionDefinitionFinder extends UsageFinder {
+
+ private final PsiElement referringElement;
+ private final String functionNameToFind;
+ private final Set<RankProfile> visited = new HashSet<>();
+
+ public FunctionDefinitionFinder(PsiElement referringElement, SearchScope scope, Processor<? super UsageInfo> processor) {
+ super(scope, processor);
+ this.referringElement = referringElement;
+ this.functionNameToFind = ReadAction.compute(() -> referringElement.getText());
+ }
+
+ public void findDefinition() {
+ SdRankProfileDefinition profileDefinition = ReadAction.compute(() -> PsiTreeUtil.getParentOfType(referringElement, SdRankProfileDefinition.class));
+ if (profileDefinition == null) return;
+ Schema schema = ReadAction.compute(() -> resolveSchema(profileDefinition));
+ RankProfile profile = ReadAction.compute(() -> schema.rankProfiles().get(profileDefinition.getName()));
+ findDefinitionAbove(profile);
+ }
+
+ private void findDefinitionAbove(RankProfile profile) {
+ ProgressIndicatorProvider.checkCanceled();
+ if ( ! visited.add(profile)) return;
+ ReadAction.compute(() -> findDefinitionIn(profile));
+ for (var parent : ReadAction.compute(() -> profile.parents().values()))
+ findDefinitionAbove(parent);
+ }
+
+ private boolean findDefinitionIn(RankProfile profile) {
+ for (var entry : profile.definedFunctions().entrySet()) {
+ // TODO: Resolve the right function in the list by parameter count
+ if (entry.getKey().equals(functionNameToFind) && entry.getValue().size() > 0)
+ processor().process(new UsageInfo(entry.getValue().get(0).definition()));
+ }
+ return true;
+ }
+
+}
diff --git a/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/FunctionUsageFinder.java b/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/FunctionUsageFinder.java
index 0900caf3ecd..15aa936cdaa 100644
--- a/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/FunctionUsageFinder.java
+++ b/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/FunctionUsageFinder.java
@@ -6,12 +6,10 @@ import ai.vespa.intellij.schema.model.RankProfile;
import ai.vespa.intellij.schema.model.Schema;
import ai.vespa.intellij.schema.psi.SdFunctionDefinition;
import ai.vespa.intellij.schema.psi.SdRankProfileDefinition;
-import ai.vespa.intellij.schema.utils.Path;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
-import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.PsiTreeUtil;
@@ -28,19 +26,16 @@ import java.util.Set;
*
* @author bratseth
*/
-public class FunctionUsageFinder {
+public class FunctionUsageFinder extends UsageFinder {
private final SdFunctionDefinition functionToFind;
private final String functionNameToFind;
- private final SearchScope scope;
- private final Processor<? super UsageInfo> processor;
private final Set<RankProfile> visited = new HashSet<>();
public FunctionUsageFinder(SdFunctionDefinition functionToFind, SearchScope scope, Processor<? super UsageInfo> processor) {
+ super(scope, processor);
this.functionToFind = functionToFind;
this.functionNameToFind = ReadAction.compute(functionToFind::getName);
- this.scope = scope;
- this.processor = processor;
}
/**
@@ -54,41 +49,28 @@ public class FunctionUsageFinder {
* on that.
*/
public void findUsages() {
- Schema schema = ReadAction.compute(this::resolveSchema);
+ Schema schema = ReadAction.compute(() -> resolveSchema(functionToFind));
var rankProfile = ReadAction.compute(() -> schema.rankProfiles()
.get(PsiTreeUtil.getParentOfType(functionToFind, SdRankProfileDefinition.class).getName()));
findUsagesBelow(rankProfile);
}
- private Schema resolveSchema() {
- PsiFile file = functionToFind.getContainingFile();
- if (file.getVirtualFile().getPath().endsWith(".profile")) {
- Path schemaFile = Path.fromString(file.getVirtualFile().getParent().getPath() + ".sd");
- return ReadAction.compute(() -> Schema.fromProjectFile(functionToFind.getProject(), schemaFile));
- }
- else { // schema
- return ReadAction.compute(() -> Schema.fromProjectFile(functionToFind.getProject(), Path.fromString(file.getVirtualFile().getPath())));
- }
- }
-
- private void findUsagesBelow(RankProfile rankProfile) {
+ private void findUsagesBelow(RankProfile profile) {
ProgressIndicatorProvider.checkCanceled();
- if (visited.contains(rankProfile)) return;
- visited.add(rankProfile);
- ReadAction.compute(() -> findUsagesIn(rankProfile));
- Collection<RankProfile> children = ReadAction.compute(() -> rankProfile.children());
- for (var child : children)
+ if ( ! visited.add(profile)) return;
+ ReadAction.compute(() -> findUsagesIn(profile));
+ for (var child : ReadAction.compute(() -> profile.children()))
findUsagesBelow(child);
}
- private boolean findUsagesIn(RankProfile rankProfile) {
- if ( ! scope.contains(rankProfile.definition().getContainingFile().getVirtualFile())) return false;
- Collection<List<Function>> functions = ReadAction.compute(() -> rankProfile.definedFunctions().values());
+ private boolean findUsagesIn(RankProfile profile) {
+ if ( ! scope().contains(profile.definition().getContainingFile().getVirtualFile())) return false;
+ Collection<List<Function>> functions = ReadAction.compute(() -> profile.definedFunctions().values());
for (var functionList : functions) {
for (var function : functionList) {
var matchingVisitor = new MatchingVisitor(functionNameToFind,
functionToFind == function.definition(),
- processor);
+ processor());
ReadAction.compute(() -> { function.definition().accept(matchingVisitor); return null; } );
}
}
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 2a83cb8e681..cefa53addba 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
@@ -31,12 +31,10 @@ public class SdFindUsagesHandler extends FindUsagesHandler {
if (elementToSearch instanceof SdFunctionDefinition) {
new FunctionUsageFinder((SdFunctionDefinition) elementToSearch, options.searchScope, processor).findUsages();
} else {
- boolean success =
- ReferencesSearch.search(createSearchParameters(elementToSearch, options.searchScope, options))
- .forEach((PsiReference ref) -> processor.process(new UsageInfo(ref)));
- if (!success) return false;
+ new FunctionDefinitionFinder(elementToSearch, options.searchScope, processor).findDefinition();
}
}
+
if (options.isSearchForTextOccurrences && options.searchScope instanceof GlobalSearchScope) {
if (options.fastTrack != null)
options.fastTrack.searchCustom(consumer -> processUsagesInText(elementToSearch,
@@ -45,6 +43,7 @@ public class SdFindUsagesHandler extends FindUsagesHandler {
else
return processUsagesInText(elementToSearch, processor, (GlobalSearchScope)options.searchScope);
}
+
return true;
}
diff --git a/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/UsageFinder.java b/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/UsageFinder.java
new file mode 100644
index 00000000000..46942c439ed
--- /dev/null
+++ b/integration/intellij/src/main/java/ai/vespa/intellij/schema/findUsages/UsageFinder.java
@@ -0,0 +1,43 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package ai.vespa.intellij.schema.findUsages;
+
+import ai.vespa.intellij.schema.model.Schema;
+import ai.vespa.intellij.schema.utils.Path;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.util.Processor;
+
+/**
+ * Usage finder base class.
+ *
+ * @author bratseth
+ */
+public abstract class UsageFinder {
+
+ private final SearchScope scope;
+ private final Processor<? super UsageInfo> processor;
+
+ protected UsageFinder(SearchScope scope, Processor<? super UsageInfo> processor) {
+ this.scope = scope;
+ this.processor = processor;
+ }
+
+ protected SearchScope scope() { return scope; }
+ protected Processor<? super UsageInfo> processor() { return processor; }
+
+ /** Returns the schema logically containing this element. */
+ protected Schema resolveSchema(PsiElement element) {
+ PsiFile file = element.getContainingFile();
+ if (file.getVirtualFile().getPath().endsWith(".profile")) {
+ Path schemaFile = Path.fromString(file.getVirtualFile().getParent().getPath() + ".sd");
+ return ReadAction.compute(() -> Schema.fromProjectFile(element.getProject(), schemaFile));
+ }
+ else { // schema
+ return ReadAction.compute(() -> Schema.fromProjectFile(element.getProject(), Path.fromString(file.getVirtualFile().getPath())));
+ }
+ }
+
+}
diff --git a/integration/intellij/src/test/java/ai/vespa/intellij/findUsages/FindDefinitionTest.java b/integration/intellij/src/test/java/ai/vespa/intellij/findUsages/FindDefinitionTest.java
new file mode 100644
index 00000000000..36fb842ce24
--- /dev/null
+++ b/integration/intellij/src/test/java/ai/vespa/intellij/findUsages/FindDefinitionTest.java
@@ -0,0 +1,24 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package ai.vespa.intellij.findUsages;
+
+import ai.vespa.intellij.PluginTestBase;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.util.Processor;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author bratseth
+ */
+public class FindDefinitionTest extends PluginTestBase {
+
+ @Test
+ public void testFindUsagesInRankProfileModularity() {
+ useDir("src/test/applications/rankprofilemodularity");
+ var tester = new UsagesTester("test.sd", getProject());
+ UsageInfo usage = tester.findFunctionDefinition("outside_schema1", 93);
+ }
+
+}
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 28c0b4f8029..141e5dd4b59 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
@@ -48,41 +48,4 @@ public class FindUsagesTest extends PluginTestBase {
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;
- this.schema = Schema.fromProjectFile(project, Path.fromString(schemaName));
- this.handler = new SdFindUsagesHandler(schema.definition());
- }
-
- List<UsageInfo> assertFunctionUsages(String explanation, int expectedUsages, String profileName, String functionName) {
- var function = schema.rankProfiles().get(profileName).definedFunctions().get(functionName).get(0).definition();
- 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;
- }
-
- }
-
- private static class MockUsageProcessor implements Processor<UsageInfo> {
-
- List<UsageInfo> usages = new ArrayList<>();
-
- @Override
- public boolean process(UsageInfo usageInfo) {
- usages.add(usageInfo);
- return true;
- }
-
- }
-
}
diff --git a/integration/intellij/src/test/java/ai/vespa/intellij/findUsages/UsagesTester.java b/integration/intellij/src/test/java/ai/vespa/intellij/findUsages/UsagesTester.java
new file mode 100644
index 00000000000..f48ef7f107a
--- /dev/null
+++ b/integration/intellij/src/test/java/ai/vespa/intellij/findUsages/UsagesTester.java
@@ -0,0 +1,67 @@
+// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package ai.vespa.intellij.findUsages;
+
+import ai.vespa.intellij.schema.findUsages.SdFindUsagesHandler;
+import ai.vespa.intellij.schema.model.Schema;
+import ai.vespa.intellij.schema.utils.Path;
+import com.intellij.find.findUsages.FindUsagesOptions;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.util.Processor;
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+class UsagesTester {
+
+ final Project project;
+ final Schema schema;
+ final SdFindUsagesHandler handler;
+ final MockUsageProcessor usageProcessor = new MockUsageProcessor();
+
+ UsagesTester(String schemaName, Project project) {
+ this.project = project;
+ this.schema = Schema.fromProjectFile(project, Path.fromString(schemaName));
+ this.handler = new SdFindUsagesHandler(schema.definition());
+ }
+
+ List<UsageInfo> assertFunctionUsages(String explanation, int expectedUsages, String profileName, String functionName) {
+ var function = schema.rankProfiles().get(profileName).definedFunctions().get(functionName).get(0).definition();
+ findUsages(function);
+ assertEquals(explanation, expectedUsages, usageProcessor.usages.size());
+ return usageProcessor.usages;
+ }
+
+ /** Finds the function referred at the given character offset in the given profile. */
+ UsageInfo findFunctionDefinition(String profileName, int offset) {
+ PsiElement referringElement = schema.rankProfiles().get(profileName).definition().findElementAt(offset);
+ findUsages(referringElement);
+ assertEquals("Expected to find definition of " + referringElement.getText(),
+ 1, usageProcessor.usages.size());
+ return usageProcessor.usages.get(0);
+ }
+
+ private void findUsages(PsiElement element) {
+ var options = new FindUsagesOptions(project);
+ usageProcessor.usages.clear();
+ options.isUsages = true;
+ handler.processElementUsages(element, usageProcessor, options);
+ }
+
+ private static class MockUsageProcessor implements Processor<UsageInfo> {
+
+ List<UsageInfo> usages = new ArrayList<>();
+
+ @Override
+ public boolean process(UsageInfo usageInfo) {
+ usages.add(usageInfo);
+ return true;
+ }
+
+ }
+
+}