summaryrefslogtreecommitdiffstats
path: root/sd-plugin/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'sd-plugin/src/main/java')
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdBlock.java60
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdChooseByNameContributor.java61
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdCodeStyleSettings.java12
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdCodeStyleSettingsProvider.java44
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdCommenter.java41
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdCompletionContributor.java30
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdFileType.java41
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdFormattingModelBuilder.java37
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdIcons.java19
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdLanguage.java16
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdLanguageCodeStyleSettingsProvider.java33
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdLexerAdapter.java11
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdRefactoringSupportProvider.java14
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdReference.java72
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdSyntaxHighlighter.java137
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdSyntaxHighlighterFactory.java17
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdUtil.java213
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdDocumentSummaryGroupingRule.java32
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdDocumentSummaryGroupingRuleProvider.java15
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesHandler.java75
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesHandlerFactory.java22
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesProvider.java68
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdRankProfileGroupingRule.java32
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdRankProfileGroupingRuleProvider.java15
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdUsageGroup.java89
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyBrowser.java76
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyNodeDescriptor.java71
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyProvider.java66
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallTreeStructure.java73
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCalleeTreeStructure.java64
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallerTreeStructure.java63
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdHierarchyUtil.java67
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/parser/SdParserDefinition.java87
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/parser/sd.bnf355
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdDeclaration.java14
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdDeclarationType.java27
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementDescriptionProvider.java29
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementFactory.java30
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementType.java13
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdFile.java26
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdIdentifier.java15
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdNamedElement.java7
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdTokenType.java18
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/psi/impl/SdNamedElementImpl.java14
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/psi/impl/SdPsiImplUtil.java352
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/sd.flex202
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewElement.java84
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewFactory.java26
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewModel.java31
49 files changed, 3016 insertions, 0 deletions
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdBlock.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdBlock.java
new file mode 100644
index 00000000000..d32baf86d7a
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdBlock.java
@@ -0,0 +1,60 @@
+package org.intellij.sdk.language;
+
+import com.intellij.formatting.Alignment;
+import com.intellij.formatting.Block;
+import com.intellij.formatting.Indent;
+import com.intellij.formatting.Spacing;
+import com.intellij.formatting.SpacingBuilder;
+import com.intellij.formatting.Wrap;
+import com.intellij.formatting.WrapType;
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.formatter.common.AbstractBlock;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SdBlock extends AbstractBlock {
+
+ private final SpacingBuilder spacingBuilder;
+
+ protected SdBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment,
+ SpacingBuilder spacingBuilder) {
+ super(node, wrap, alignment);
+ this.spacingBuilder = spacingBuilder;
+ }
+
+ @Override
+ protected List<Block> buildChildren() {
+ List<Block> blocks = new ArrayList<>();
+ ASTNode child = myNode.getFirstChildNode();
+ while (child != null) {
+ if (child.getElementType() != TokenType.WHITE_SPACE) {
+ Block block = new SdBlock(child, Wrap.createWrap(WrapType.NONE, false), Alignment.createAlignment(),
+ spacingBuilder);
+ blocks.add(block);
+ }
+ child = child.getTreeNext();
+ }
+ return blocks;
+ }
+
+ @Override
+ public Indent getIndent() {
+ return Indent.getNoneIndent();
+ }
+
+ @Nullable
+ @Override
+ public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) {
+ return spacingBuilder.getSpacing(this, child1, child2);
+ }
+
+ @Override
+ public boolean isLeaf() {
+ return myNode.getFirstChildNode() == null;
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdChooseByNameContributor.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdChooseByNameContributor.java
new file mode 100644
index 00000000000..45e26f401d4
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdChooseByNameContributor.java
@@ -0,0 +1,61 @@
+package org.intellij.sdk.language;
+
+import com.intellij.navigation.ChooseByNameContributor;
+import com.intellij.navigation.NavigationItem;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.search.FileTypeIndex;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.indexing.FileBasedIndex;
+import org.intellij.sdk.language.psi.SdDeclaration;
+import org.intellij.sdk.language.psi.SdFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class SdChooseByNameContributor implements ChooseByNameContributor {
+
+ @Override
+ public String @NotNull [] getNames(Project project, boolean includeNonProjectItems) {
+ Collection<VirtualFile> virtualFiles = FileBasedIndex.getInstance().getContainingFiles(
+ FileTypeIndex.NAME,
+ SdFileType.INSTANCE,
+ GlobalSearchScope.allScope(project)
+ );
+
+ List<SdDeclaration> declarations = new ArrayList<>();
+
+ for (VirtualFile file : virtualFiles) {
+ SdFile sdFile = (SdFile) PsiManager.getInstance(project).findFile(file);
+ declarations.addAll(SdUtil.findDeclarations(sdFile));
+ }
+
+ List<String> names = new ArrayList<>(declarations.size());
+ for (SdDeclaration declaration : declarations) {
+ names.add(declaration.getName());
+ }
+ return names.toArray(new String[names.size()]);
+ }
+
+ @Override
+ public NavigationItem @NotNull [] getItemsByName(String name, String pattern, Project project, boolean includeNonProjectItems) {
+ Collection<VirtualFile> virtualFiles = FileBasedIndex.getInstance().getContainingFiles(
+ FileTypeIndex.NAME,
+ SdFileType.INSTANCE,
+ GlobalSearchScope.allScope(project)
+ );
+
+ List<SdDeclaration> declarations = new ArrayList<>();
+
+ for (VirtualFile file : virtualFiles) {
+ SdFile sdFile = (SdFile) PsiManager.getInstance(project).findFile(file);
+ declarations.addAll(SdUtil.findDeclarationsByName(sdFile, name));
+ }
+
+ return declarations.toArray(new NavigationItem[declarations.size()]);
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdCodeStyleSettings.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdCodeStyleSettings.java
new file mode 100644
index 00000000000..0719ac7f426
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdCodeStyleSettings.java
@@ -0,0 +1,12 @@
+package org.intellij.sdk.language;
+
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
+
+public class SdCodeStyleSettings extends CustomCodeStyleSettings {
+
+ public SdCodeStyleSettings(CodeStyleSettings settings) {
+ super("SdCodeStyleSettings", settings);
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdCodeStyleSettingsProvider.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdCodeStyleSettingsProvider.java
new file mode 100644
index 00000000000..6ea68655c70
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdCodeStyleSettingsProvider.java
@@ -0,0 +1,44 @@
+package org.intellij.sdk.language;
+
+import com.intellij.application.options.CodeStyleAbstractConfigurable;
+import com.intellij.application.options.CodeStyleAbstractPanel;
+import com.intellij.application.options.TabbedLanguageCodeStylePanel;
+import com.intellij.psi.codeStyle.CodeStyleConfigurable;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
+import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class SdCodeStyleSettingsProvider extends CodeStyleSettingsProvider {
+
+ @Override
+ public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) {
+ return new SdCodeStyleSettings(settings);
+ }
+
+ @Nullable
+ @Override
+ public String getConfigurableDisplayName() {
+ return "Sd";
+ }
+
+ @NotNull
+ public CodeStyleConfigurable createConfigurable(@NotNull CodeStyleSettings settings, @NotNull CodeStyleSettings modelSettings) {
+ return new CodeStyleAbstractConfigurable(settings, modelSettings, this.getConfigurableDisplayName()) {
+ @Override
+ protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings) {
+ return new SdCodeStyleMainPanel(getCurrentSettings(), settings);
+ }
+ };
+ }
+
+ private static class SdCodeStyleMainPanel extends TabbedLanguageCodeStylePanel {
+
+ public SdCodeStyleMainPanel(CodeStyleSettings currentSettings, CodeStyleSettings settings) {
+ super(SdLanguage.INSTANCE, currentSettings, settings);
+ }
+
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdCommenter.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdCommenter.java
new file mode 100644
index 00000000000..e0fc30df22b
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdCommenter.java
@@ -0,0 +1,41 @@
+package org.intellij.sdk.language;
+
+import com.intellij.lang.Commenter;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * This class enables turning a line into a comment with "Code -> Comment with line comment"
+ */
+public class SdCommenter implements Commenter {
+
+ @Nullable
+ @Override
+ public String getLineCommentPrefix() {
+ return "#";
+ }
+
+ @Nullable
+ @Override
+ public String getBlockCommentPrefix() {
+ return "";
+ }
+
+ @Nullable
+ @Override
+ public String getBlockCommentSuffix() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public String getCommentedBlockCommentPrefix() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public String getCommentedBlockCommentSuffix() {
+ return null;
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdCompletionContributor.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdCompletionContributor.java
new file mode 100644
index 00000000000..5dd67e5b6e6
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdCompletionContributor.java
@@ -0,0 +1,30 @@
+package org.intellij.sdk.language;
+
+import com.intellij.codeInsight.completion.CompletionContributor;
+import com.intellij.codeInsight.completion.CompletionParameters;
+import com.intellij.codeInsight.completion.CompletionProvider;
+import com.intellij.codeInsight.completion.CompletionResultSet;
+import com.intellij.codeInsight.completion.CompletionType;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.patterns.PlatformPatterns;
+import com.intellij.util.ProcessingContext;
+import org.intellij.sdk.language.psi.SdTypes;
+import org.jetbrains.annotations.NotNull;
+
+public class SdCompletionContributor extends CompletionContributor {
+
+
+ public SdCompletionContributor() {
+ extend(CompletionType.BASIC,
+ PlatformPatterns.psiElement(SdTypes.IDENTIFIER_VAL),
+ new CompletionProvider<>() {
+ public void addCompletions(@NotNull CompletionParameters parameters, //completion parameters contain details of the cursor position
+ @NotNull ProcessingContext context,
+ @NotNull CompletionResultSet resultSet) { //result set contains completion details to suggest
+ resultSet.addElement(LookupElementBuilder.create(""));
+ }
+ }
+ );
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdFileType.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdFileType.java
new file mode 100644
index 00000000000..eeed80ad9f1
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdFileType.java
@@ -0,0 +1,41 @@
+package org.intellij.sdk.language;
+
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.Icon;
+
+public class SdFileType extends LanguageFileType {
+
+ public static final SdFileType INSTANCE = new SdFileType();
+
+ private SdFileType() {
+ super(SdLanguage.INSTANCE);
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return "Sd File";
+ }
+
+ @NotNull
+ @Override
+ public String getDescription() {
+ return "Sd language file";
+ }
+
+ @NotNull
+ @Override
+ public String getDefaultExtension() {
+ return "sd";
+ }
+
+ @Nullable
+ @Override
+ public Icon getIcon() {
+ return SdIcons.FILE;
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdFormattingModelBuilder.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdFormattingModelBuilder.java
new file mode 100644
index 00000000000..35f57f65c26
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdFormattingModelBuilder.java
@@ -0,0 +1,37 @@
+package org.intellij.sdk.language;
+
+import com.intellij.formatting.Alignment;
+import com.intellij.formatting.FormattingContext;
+import com.intellij.formatting.FormattingModel;
+import com.intellij.formatting.FormattingModelBuilder;
+import com.intellij.formatting.FormattingModelProvider;
+import com.intellij.formatting.SpacingBuilder;
+import com.intellij.formatting.Wrap;
+import com.intellij.formatting.WrapType;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import org.intellij.sdk.language.psi.SdTypes;
+import org.jetbrains.annotations.NotNull;
+
+public class SdFormattingModelBuilder implements FormattingModelBuilder {
+
+ private static SpacingBuilder createSpaceBuilder(CodeStyleSettings settings) {
+ return new SpacingBuilder(settings, SdLanguage.INSTANCE)
+ .around(SdTypes.SYMBOL)
+ .spaceIf(settings.getCommonSettings(SdLanguage.INSTANCE.getID()).SPACE_AFTER_COLON)
+ .before(SdTypes.DOCUMENT_FIELD_DEFINITION)
+ .none();
+ }
+
+ @Override
+ public @NotNull FormattingModel createModel(@NotNull FormattingContext formattingContext) {
+ final CodeStyleSettings codeStyleSettings = formattingContext.getCodeStyleSettings();
+ return FormattingModelProvider
+ .createFormattingModelForPsiFile(formattingContext.getContainingFile(),
+ new SdBlock(formattingContext.getNode(),
+ Wrap.createWrap(WrapType.NONE, false),
+ Alignment.createAlignment(),
+ createSpaceBuilder(codeStyleSettings)),
+ codeStyleSettings);
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdIcons.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdIcons.java
new file mode 100644
index 00000000000..8dadda25774
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdIcons.java
@@ -0,0 +1,19 @@
+package org.intellij.sdk.language;
+
+import com.intellij.openapi.util.IconLoader;
+
+import javax.swing.Icon;
+
+public class SdIcons {
+ public static final Icon FILE = IconLoader.getIcon("icons/sd_icon.png", SdIcons.class);
+ public static final Icon STRUCT_FIELD = IconLoader.getIcon("icons/struct_field_icon.png", SdIcons.class);
+ public static final Icon IMPORTED_FIELD = IconLoader.getIcon("icons/imported_field_icon.png", SdIcons.class);
+ public static final Icon DOCUMENT_SUMMARY = IconLoader.getIcon("icons/document_summary_icon.png", SdIcons.class);
+ public static final Icon STRUCT = IconLoader.getIcon("icons/struct_icon.png", SdIcons.class);
+ public static final Icon DOCUMENT = IconLoader.getIcon("icons/document_icon.png", SdIcons.class);
+ public static final Icon SUMMARY = IconLoader.getIcon("icons/summary_def_icon.png", SdIcons.class);
+ public static final Icon MACRO = IconLoader.getIcon("icons/macro_icon.png", SdIcons.class);
+ public static final Icon OVERRIDE_MACRO = IconLoader.getIcon("icons/override_macro_icon.png", SdIcons.class);
+ public static final Icon FIRST_PHASE = IconLoader.getIcon("icons/first_phase_icon.png", SdIcons.class);
+}
+ \ No newline at end of file
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdLanguage.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdLanguage.java
new file mode 100644
index 00000000000..7dbf10b68ac
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdLanguage.java
@@ -0,0 +1,16 @@
+package org.intellij.sdk.language;
+
+import com.intellij.lang.Language;
+
+public class SdLanguage extends Language {
+ public static final SdLanguage INSTANCE = new SdLanguage();
+
+ private SdLanguage() {
+ super("Sd");
+ }
+
+ @Override
+ public boolean isCaseSensitive() {
+ return true;
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdLanguageCodeStyleSettingsProvider.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdLanguageCodeStyleSettingsProvider.java
new file mode 100644
index 00000000000..b51ae286201
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdLanguageCodeStyleSettingsProvider.java
@@ -0,0 +1,33 @@
+package org.intellij.sdk.language;
+
+import com.intellij.lang.Language;
+import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable;
+import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
+import org.jetbrains.annotations.NotNull;
+
+public class SdLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettingsProvider {
+
+ @NotNull
+ @Override
+ public Language getLanguage() {
+ return SdLanguage.INSTANCE;
+ }
+
+ @Override
+ public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @NotNull SettingsType settingsType) {
+ if (settingsType == SettingsType.SPACING_SETTINGS) {
+ consumer.showStandardOptions("SPACE_AFTER_COLON");
+// consumer.renameStandardOption("SPACE_AROUND_ASSIGNMENT_OPERATORS", "Separator");
+ } else if (settingsType == SettingsType.BLANK_LINES_SETTINGS) {
+ consumer.showStandardOptions("KEEP_BLANK_LINES_IN_CODE");
+// } else if (settingsType == SettingsType.INDENT_SETTINGS) {
+// consumer.showStandardOptions("USE_RELATIVE_INDENTS");
+ }
+ }
+
+ @Override
+ public String getCodeSample(@NotNull SettingsType settingsType) {
+ return "field myField type int {\n indexing: summary\n}";
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdLexerAdapter.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdLexerAdapter.java
new file mode 100644
index 00000000000..3363ce730b8
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdLexerAdapter.java
@@ -0,0 +1,11 @@
+package org.intellij.sdk.language;
+
+import com.intellij.lexer.FlexAdapter;
+import org.intellij.sdk.language.lexer.SdLexer;
+
+public class SdLexerAdapter extends FlexAdapter {
+
+ public SdLexerAdapter() {
+ super(new SdLexer(null));
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdRefactoringSupportProvider.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdRefactoringSupportProvider.java
new file mode 100644
index 00000000000..5867729d54d
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdRefactoringSupportProvider.java
@@ -0,0 +1,14 @@
+package org.intellij.sdk.language;
+
+import com.intellij.lang.refactoring.RefactoringSupportProvider;
+import com.intellij.psi.PsiElement;
+import org.intellij.sdk.language.psi.SdIdentifierVal;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class SdRefactoringSupportProvider extends RefactoringSupportProvider {
+ @Override
+ public boolean isMemberInplaceRenameAvailable(@NotNull PsiElement elementToRename, @Nullable PsiElement context) {
+ return (elementToRename instanceof SdIdentifierVal);
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdReference.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdReference.java
new file mode 100644
index 00000000000..891d94e15cb
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdReference.java
@@ -0,0 +1,72 @@
+package org.intellij.sdk.language;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementResolveResult;
+import com.intellij.psi.PsiPolyVariantReference;
+import com.intellij.psi.PsiReferenceBase;
+import com.intellij.psi.ResolveResult;
+import com.intellij.util.IncorrectOperationException;
+import org.intellij.sdk.language.psi.SdDeclaration;
+import org.intellij.sdk.language.psi.SdIdentifierVal;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SdReference extends PsiReferenceBase<PsiElement> implements PsiPolyVariantReference {
+
+ private final String elementName;
+
+ public SdReference(@NotNull PsiElement element, TextRange textRange) {
+ super(element, textRange);
+ elementName = element.getText().substring(textRange.getStartOffset(), textRange.getEndOffset());
+ }
+
+ @NotNull
+ @Override
+ public ResolveResult @NotNull [] multiResolve(boolean incompleteCode) {
+
+ PsiElement file = myElement.getContainingFile();
+
+ final List<SdDeclaration> declarations = SdUtil.findDeclarationsByScope(file, myElement, elementName);
+
+ List<ResolveResult> results = new ArrayList<>();
+
+ for (SdDeclaration declaration : declarations) {
+ results.add(new PsiElementResolveResult(declaration));
+ }
+ return results.toArray(new ResolveResult[results.size()]);
+ }
+
+ @Nullable
+ @Override
+ public PsiElement resolve() {
+ ResolveResult[] resolveResults = multiResolve(false);
+ return resolveResults.length == 1 ? resolveResults[0].getElement() : null;
+ }
+
+ @Override
+ public Object @NotNull [] getVariants() {
+ List<SdDeclaration> declarations = SdUtil.findDeclarations(myElement.getContainingFile());
+ List<LookupElement> variants = new ArrayList<>();
+ for (final SdDeclaration element : declarations) {
+ if (element.getName() != null && element.getName().length() > 0) {
+ variants.add(LookupElementBuilder
+ .create(element).withIcon(SdIcons.FILE)
+ .withTypeText(element.getContainingFile().getName())
+ );
+ }
+ }
+ return variants.toArray();
+ }
+
+ @Override
+ public PsiElement handleElementRename(@NotNull String newElementName) throws IncorrectOperationException {
+ return ((SdIdentifierVal) myElement).setName(newElementName);
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdSyntaxHighlighter.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdSyntaxHighlighter.java
new file mode 100644
index 00000000000..ea2e6331c38
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdSyntaxHighlighter.java
@@ -0,0 +1,137 @@
+package org.intellij.sdk.language;
+
+import static com.intellij.openapi.editor.colors.TextAttributesKey.createTextAttributesKey;
+
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
+import com.intellij.openapi.editor.HighlighterColors;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.tree.IElementType;
+import org.intellij.sdk.language.psi.SdTypes;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashSet;
+
+public class SdSyntaxHighlighter extends SyntaxHighlighterBase {
+
+ private static final HashSet<IElementType> keyWordsSet = initKeyWordsSet();
+ private static final HashSet<IElementType> constantsSet = initConstantsSet();
+// private static final HashSet<IElementType> symbols = initSymbolsSet();
+
+
+ public static final TextAttributesKey IDENTIFIER =
+ createTextAttributesKey("SD_IDENTIFIER", DefaultLanguageHighlighterColors.INSTANCE_FIELD);
+ public static final TextAttributesKey CONSTANT =
+ createTextAttributesKey("SD_CONSTANT", DefaultLanguageHighlighterColors.CONSTANT);
+ public static final TextAttributesKey KEY =
+ createTextAttributesKey("SD_KEY", DefaultLanguageHighlighterColors.KEYWORD);
+ public static final TextAttributesKey SYMBOL =
+ createTextAttributesKey("SD_SYMBOL", DefaultLanguageHighlighterColors.BRACKETS);
+ public static final TextAttributesKey STRING =
+ createTextAttributesKey("SD_STRING", DefaultLanguageHighlighterColors.STRING);
+ public static final TextAttributesKey COMMENT =
+ createTextAttributesKey("SD_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT);
+ public static final TextAttributesKey BAD_CHARACTER =
+ createTextAttributesKey("Sd_BAD_CHARACTER", HighlighterColors.BAD_CHARACTER);
+
+
+ private static final TextAttributesKey[] BAD_CHAR_KEYS = new TextAttributesKey[]{BAD_CHARACTER};
+ private static final TextAttributesKey[] IDENTIFIER_KEYS = new TextAttributesKey[]{IDENTIFIER};
+ private static final TextAttributesKey[] CONSTANT_KEYS = new TextAttributesKey[]{CONSTANT};
+ private static final TextAttributesKey[] KEY_KEYS = new TextAttributesKey[]{KEY};
+ private static final TextAttributesKey[] SYMBOL_KEYS = new TextAttributesKey[]{SYMBOL};
+ private static final TextAttributesKey[] STRING_KEYS = new TextAttributesKey[]{STRING};
+ private static final TextAttributesKey[] COMMENT_KEYS = new TextAttributesKey[]{COMMENT};
+ private static final TextAttributesKey[] EMPTY_KEYS = new TextAttributesKey[0];
+
+ @NotNull
+ @Override
+ public Lexer getHighlightingLexer() {
+ return new SdLexerAdapter();
+ }
+
+ @NotNull
+ @Override
+ public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
+ if (tokenType.equals(SdTypes.IDENTIFIER_VAL)) {
+ return IDENTIFIER_KEYS;
+// } else if (tokenType.equals(SdTypes.KEY)) {
+// return KEY_KEYS;
+// } else if (tokenType.equals(SdTypes.VALUE)) {
+// return VALUE_KEYS;
+ } else if (keyWordsSet.contains(tokenType)) {
+ return KEY_KEYS;
+ } else if (tokenType.equals(SdTypes.SYMBOL)) {
+ return SYMBOL_KEYS;
+ } else if (tokenType.equals(SdTypes.STRING)) {
+ return STRING_KEYS;
+ } else if (tokenType.equals(SdTypes.COMMENT)) {
+ return COMMENT_KEYS;
+ } else if (constantsSet.contains(tokenType)) {
+ return CONSTANT_KEYS;
+ } else if (tokenType.equals(TokenType.BAD_CHARACTER)) {
+ return BAD_CHAR_KEYS;
+ } else {
+ return EMPTY_KEYS;
+ }
+ }
+
+// private static HashSet<IElementType> initSymbolsSet() {
+// HashSet<IElementType> symbols = new HashSet<>();
+// symbols.add('{');
+// return symbols;
+// }
+
+ private static HashSet<IElementType> initKeyWordsSet() {
+ HashSet<IElementType> keyWords = new HashSet<>();
+ keyWords.add(SdTypes.MACRO);
+ keyWords.add(SdTypes.FIELD);
+ keyWords.add(SdTypes.TYPE);
+ keyWords.add(SdTypes.SEARCH);
+ keyWords.add(SdTypes.DOCUMENT);
+ keyWords.add(SdTypes.INHERITS);
+ keyWords.add(SdTypes.STRUCT);
+ keyWords.add(SdTypes.STRUCT_FIELD);
+ keyWords.add(SdTypes.MATCH);
+ keyWords.add(SdTypes.INDEXING);
+ keyWords.add(SdTypes.RANK);
+ keyWords.add(SdTypes.INDEXING_REWRITE);
+ keyWords.add(SdTypes.QUERY_COMMAND);
+ return keyWords;
+ }
+
+ private static HashSet<IElementType> initConstantsSet() {
+ HashSet<IElementType> constants = new HashSet<>();
+ constants.add(SdTypes.SUMMARY);
+ constants.add(SdTypes.ATTRIBUTE);
+ constants.add(SdTypes.TEXT);
+ constants.add(SdTypes.EXACT);
+ constants.add(SdTypes.EXACT_TERMINATOR);
+ constants.add(SdTypes.WORD);
+ constants.add(SdTypes.PREFIX);
+ constants.add(SdTypes.CASED);
+ constants.add(SdTypes.UNCASED);
+ constants.add(SdTypes.SUBSTRING);
+ constants.add(SdTypes.SUFFIX);
+ constants.add(SdTypes.MAX_LENGTH);
+ constants.add(SdTypes.GRAM);
+ constants.add(SdTypes.GRAM_SIZE);
+ constants.add(SdTypes.INDEX);
+ constants.add(SdTypes.FAST_SEARCH);
+ constants.add(SdTypes.FAST_ACCESS);
+ constants.add(SdTypes.ALIAS);
+ constants.add(SdTypes.SORTING);
+ constants.add(SdTypes.DISTANCE_METRIC);
+ constants.add(SdTypes.FILTER);
+ constants.add(SdTypes.NORMAL);
+ constants.add(SdTypes.NONE);
+ constants.add(SdTypes.FULL);
+ constants.add(SdTypes.DYNAMIC);
+ constants.add(SdTypes.MATCHED_ELEMENTS_ONLY);
+
+ return constants;
+ }
+}
+
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdSyntaxHighlighterFactory.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdSyntaxHighlighterFactory.java
new file mode 100644
index 00000000000..c4bc4491bf1
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdSyntaxHighlighterFactory.java
@@ -0,0 +1,17 @@
+package org.intellij.sdk.language;
+
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+
+public class SdSyntaxHighlighterFactory extends SyntaxHighlighterFactory {
+
+ @NotNull
+ @Override
+ public SyntaxHighlighter getSyntaxHighlighter(Project project, VirtualFile virtualFile) {
+ return new SdSyntaxHighlighter();
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/SdUtil.java b/sd-plugin/src/main/java/org/intellij/sdk/language/SdUtil.java
new file mode 100644
index 00000000000..4dd2fe8cac1
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/SdUtil.java
@@ -0,0 +1,213 @@
+package org.intellij.sdk.language;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.search.FileTypeIndex;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.indexing.FileBasedIndex;
+import org.intellij.sdk.language.psi.SdArgumentDefinition;
+import org.intellij.sdk.language.psi.SdDeclaration;
+import org.intellij.sdk.language.psi.SdDocumentDefinition;
+import org.intellij.sdk.language.psi.SdDocumentFieldDefinition;
+import org.intellij.sdk.language.psi.SdDocumentStructDefinition;
+import org.intellij.sdk.language.psi.SdDocumentStructFieldDefinition;
+import org.intellij.sdk.language.psi.SdDocumentSummaryDefinition;
+import org.intellij.sdk.language.psi.SdFieldTypeName;
+import org.intellij.sdk.language.psi.SdFile;
+import org.intellij.sdk.language.psi.SdFunctionDefinition;
+import org.intellij.sdk.language.psi.SdIdentifier;
+import org.intellij.sdk.language.psi.SdImportFieldDefinition;
+import org.intellij.sdk.language.psi.SdRankProfileDefinition;
+import org.intellij.sdk.language.psi.SdSchemaFieldDefinition;
+import org.intellij.sdk.language.psi.SdSummaryDefinition;
+import org.intellij.sdk.language.psi.SdTypes;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+
+public class SdUtil {
+
+ public static @NotNull HashMap<String, List<PsiElement>> createMacrosMap(SdFile file) {
+ HashMap<String, List<PsiElement>> macrosMap = new HashMap<>();
+ for (SdRankProfileDefinition rankProfile : PsiTreeUtil
+ .findChildrenOfType(file, SdRankProfileDefinition.class)) {
+ for (SdFunctionDefinition macro : PsiTreeUtil.findChildrenOfType(rankProfile, SdFunctionDefinition.class)) {
+ macrosMap.computeIfAbsent(macro.getName(), k -> new ArrayList<>()).add(macro);
+ }
+ }
+ return macrosMap;
+ }
+
+ /**
+ * @param baseRankProfile the rank-profile node to find its parent
+ * @return the rank-profile that the baseRankProfile inherits from, or null if it doesn't exist
+ */
+ public static PsiElement getRankProfileParent(SdRankProfileDefinition baseRankProfile) {
+ if (baseRankProfile == null) {
+ return null;
+ }
+ ASTNode inheritsNode = baseRankProfile.getNode().findChildByType(SdTypes.INHERITS);
+ if (inheritsNode == null) {
+ return null;
+ }
+ ASTNode ancestorAST = baseRankProfile.getNode().findChildByType(SdTypes.IDENTIFIER_VAL, inheritsNode);
+ if (ancestorAST == null) {
+ ancestorAST = baseRankProfile.getNode().findChildByType(SdTypes.IDENTIFIER_WITH_DASH_VAL, inheritsNode);
+ if (ancestorAST == null) {
+ return null;
+ }
+ }
+ SdIdentifier ancestorIdentifier = (SdIdentifier) ancestorAST.getPsi();
+ return ancestorIdentifier.getReference().resolve();
+
+ }
+
+ public static String createFunctionDescription(SdFunctionDefinition macro) {
+ SdRankProfileDefinition rankProfile = PsiTreeUtil.getParentOfType(macro, SdRankProfileDefinition.class);
+ String rankProfileName;
+ if (rankProfile != null) {
+ rankProfileName = rankProfile.getName();
+ List<SdArgumentDefinition> args = macro.getArgumentDefinitionList();
+ StringBuilder text = new StringBuilder(rankProfileName + "." + macro.getName() + "(");
+ for (int i = 0; i < args.size(); i++) {
+ text.append(args.get(i).getName());
+ if (i < args.size() - 1) {
+ text.append(", ");
+ }
+ }
+ text.append(")");
+ return text.toString();
+ } else {
+ return macro.getName();
+ }
+ }
+
+ public static List<SdDeclaration> findDeclarationsByName(PsiElement file, String name) {
+ List<SdDeclaration> result = new ArrayList<>();
+
+ for (SdDeclaration declaration : PsiTreeUtil.collectElementsOfType(file, SdDeclaration.class)) {
+ if (name.equals(declaration.getName())) {
+ result.add(declaration);
+ }
+ }
+ return result;
+ }
+
+
+ public static List<SdDeclaration> findDeclarationsByScope(PsiElement file, PsiElement element, String name) {
+ List<SdDeclaration> result = new ArrayList<>();
+
+ // If element is a field declared in another file (to be imported), return the declaration from the other file
+ // if found, else return an empty result list
+ if (element.getParent() instanceof SdImportFieldDefinition &&
+ element.getNextSibling().getNextSibling().getText().equals("as")) {
+ Project project = file.getProject();
+
+ PsiReference docFieldRef = element.getPrevSibling().getPrevSibling().getReference();
+ PsiElement docField = docFieldRef != null ? docFieldRef.resolve() : null;
+ SdFieldTypeName fieldType = docField != null ? PsiTreeUtil.findChildOfType(docField, SdFieldTypeName.class) : null;
+ SdIdentifier docIdentifier = fieldType != null ? PsiTreeUtil.findChildOfType(fieldType, SdIdentifier.class) : null;
+ String docName = docIdentifier != null ? docIdentifier.getName() : null;
+ if (docName == null) {
+ return result;
+ }
+
+ Collection<VirtualFile> virtualFiles = FileBasedIndex.getInstance().getContainingFiles(
+ FileTypeIndex.NAME,
+ SdFileType.INSTANCE,
+ GlobalSearchScope.allScope(project)
+ );
+ for (VirtualFile vfile : virtualFiles) {
+ SdFile sdFile = (SdFile) PsiManager.getInstance(project).findFile(vfile);
+ if (sdFile != null && !sdFile.getName().equals(docName + ".sd")) {
+ continue;
+ }
+ result.addAll(SdUtil.findDeclarationsByName(sdFile, name));
+ }
+ return result;
+ }
+
+ // If element is the macro's name in the macro definition, return the macro definition
+ if (element.getParent() instanceof SdFunctionDefinition) {
+ result.add((SdDeclaration) element.getParent());
+ return result;
+ }
+
+ // Check if element is inside a macro body
+ SdFunctionDefinition macroParent = PsiTreeUtil.getParentOfType(element, SdFunctionDefinition.class);
+ if (macroParent != null) {
+ for (SdArgumentDefinition arg : PsiTreeUtil.findChildrenOfType(macroParent, SdArgumentDefinition.class)) {
+ if (name.equals(arg.getName())) { // if the element was declared as an argument of the macro
+ result.add(arg);
+ return result;
+ }
+ }
+ }
+
+ // If element is a macro's name, return the most specific declaration of the macro
+ if (((SdIdentifier) element).isFunctionName(file)) {
+ PsiElement curRankProfile = PsiTreeUtil.getParentOfType(element, SdRankProfileDefinition.class);
+ while (curRankProfile != null) {
+ for (SdFunctionDefinition macro : PsiTreeUtil.collectElementsOfType(curRankProfile, SdFunctionDefinition.class)) {
+ if (macro.getName().equals(name)) {
+ result.add(macro);
+ return result;
+ }
+ }
+ curRankProfile = getRankProfileParent((SdRankProfileDefinition) curRankProfile);
+ }
+ }
+
+ for (PsiElement declaration : PsiTreeUtil.collectElements(file, psiElement ->
+ psiElement instanceof SdDeclaration && !(psiElement instanceof SdArgumentDefinition))) {
+ if (name.equals(((SdDeclaration) declaration).getName())) {
+ result.add((SdDeclaration) declaration);
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ public static List<SdDeclaration> findDeclarations(PsiElement element) {
+ return new ArrayList<>(PsiTreeUtil.collectElementsOfType(element, SdDeclaration.class));
+ }
+
+ public static List<PsiElement> findSchemaChildren(PsiElement element) {
+ return new ArrayList<>(PsiTreeUtil.collectElementsOfType(element, new Class[]{SdDocumentDefinition.class,
+ SdSchemaFieldDefinition.class,
+ SdImportFieldDefinition.class,
+ SdDocumentSummaryDefinition.class,
+ SdRankProfileDefinition.class}));
+ }
+
+ public static List<PsiElement> findDocumentChildren(PsiElement element) {
+ return new ArrayList<>(PsiTreeUtil.collectElementsOfType(element, new Class[]{SdDocumentStructDefinition.class,
+ SdDocumentFieldDefinition.class}));
+ }
+
+ public static List<PsiElement> findDocumentStructChildren(PsiElement element) {
+ return new ArrayList<>(PsiTreeUtil.collectElementsOfType(element,
+ SdDocumentStructFieldDefinition.class));
+ }
+
+ public static List<PsiElement> findRankProfileChildren(PsiElement element) {
+ return new ArrayList<>(PsiTreeUtil.collectElementsOfType(element,
+ SdFunctionDefinition.class));
+ }
+
+ public static List<PsiElement> findDocumentSummaryChildren(PsiElement element) {
+ return new ArrayList<>(PsiTreeUtil.collectElementsOfType(element,
+ SdSummaryDefinition.class));
+ }
+
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdDocumentSummaryGroupingRule.java b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdDocumentSummaryGroupingRule.java
new file mode 100644
index 00000000000..d4d38c8c38a
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdDocumentSummaryGroupingRule.java
@@ -0,0 +1,32 @@
+package org.intellij.sdk.language.findUsages;
+
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.psi.PsiElement;
+import com.intellij.usages.Usage;
+import com.intellij.usages.UsageGroup;
+import com.intellij.usages.UsageTarget;
+import com.intellij.usages.rules.PsiElementUsage;
+import com.intellij.usages.rules.SingleParentUsageGroupingRule;
+import org.intellij.sdk.language.SdLanguage;
+import org.intellij.sdk.language.psi.SdDocumentSummaryDefinition;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class SdDocumentSummaryGroupingRule extends SingleParentUsageGroupingRule implements DumbAware {
+
+ @Override
+ protected @Nullable UsageGroup getParentGroupFor(@NotNull Usage usage, UsageTarget @NotNull [] targets) {
+ PsiElement psiElement = usage instanceof PsiElementUsage ? ((PsiElementUsage)usage).getElement() : null;
+ if (psiElement == null || psiElement.getLanguage() != SdLanguage.INSTANCE) return null;
+
+ while (psiElement != null) {
+ if (psiElement instanceof SdDocumentSummaryDefinition) {
+ final SdDocumentSummaryDefinition componentElement = (SdDocumentSummaryDefinition) psiElement;
+ return new SdUsageGroup(componentElement);
+ }
+ psiElement = psiElement.getParent();
+ }
+
+ return null;
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdDocumentSummaryGroupingRuleProvider.java b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdDocumentSummaryGroupingRuleProvider.java
new file mode 100644
index 00000000000..ffd620c822e
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdDocumentSummaryGroupingRuleProvider.java
@@ -0,0 +1,15 @@
+package org.intellij.sdk.language.findUsages;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.usages.impl.FileStructureGroupRuleProvider;
+import com.intellij.usages.rules.UsageGroupingRule;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class SdDocumentSummaryGroupingRuleProvider implements FileStructureGroupRuleProvider {
+
+ @Override
+ public @Nullable UsageGroupingRule getUsageGroupingRule(@NotNull Project project) {
+ return new SdDocumentSummaryGroupingRule();
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesHandler.java b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesHandler.java
new file mode 100644
index 00000000000..f00ea940613
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesHandler.java
@@ -0,0 +1,75 @@
+package org.intellij.sdk.language.findUsages;
+
+import com.intellij.find.findUsages.FindUsagesHandler;
+import com.intellij.find.findUsages.FindUsagesOptions;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.application.ReadActionProcessor;
+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.usageView.UsageInfo;
+import com.intellij.util.Processor;
+import org.intellij.sdk.language.SdUtil;
+import org.intellij.sdk.language.psi.SdFile;
+import org.intellij.sdk.language.psi.SdFunctionDefinition;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.List;
+
+public class SdFindUsagesHandler extends FindUsagesHandler {
+
+ protected HashMap<String, List<PsiElement>> macrosMap;
+
+ protected SdFindUsagesHandler(@NotNull PsiElement psiElement) {
+ super(psiElement);
+ PsiFile file = psiElement.getContainingFile();
+ macrosMap = file instanceof SdFile ? SdUtil.createMacrosMap((SdFile) psiElement.getContainingFile()) : new HashMap<>();
+ }
+
+ @Override
+ public boolean processElementUsages(@NotNull final PsiElement elementToSearch,
+ @NotNull final Processor<? super UsageInfo> processor,
+ @NotNull final FindUsagesOptions options) {
+ final ReadActionProcessor<PsiReference> refProcessor = new ReadActionProcessor<>() {
+ @Override
+ public boolean processInReadAction(final PsiReference ref) {
+ return processor.process(new UsageInfo(ref));
+ }
+ };
+
+ final SearchScope scope = options.searchScope;
+
+ final boolean searchText = options.isSearchForTextOccurrences && scope instanceof GlobalSearchScope;
+
+ if (options.isUsages) {
+ if (!(elementToSearch instanceof SdFunctionDefinition)) {
+ boolean success =
+ ReferencesSearch.search(createSearchParameters(elementToSearch, scope, options)).forEach(refProcessor);
+ if (!success) return false;
+ } else {
+ String macroName = ReadAction.compute( ((SdFunctionDefinition) elementToSearch)::getName);
+
+ for (PsiElement macroImpl : macrosMap.get(macroName)) {
+ boolean success =
+ ReferencesSearch.search(createSearchParameters(macroImpl, scope, options)).forEach(refProcessor);
+ if (!success) return false;
+ }
+ }
+ }
+ if (searchText) {
+ if (options.fastTrack != null) {
+ options.fastTrack.searchCustom(consumer -> processUsagesInText(elementToSearch, processor, (GlobalSearchScope)scope));
+ }
+ else {
+ return processUsagesInText(elementToSearch, processor, (GlobalSearchScope)scope);
+ }
+ }
+
+ return true;
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesHandlerFactory.java b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesHandlerFactory.java
new file mode 100644
index 00000000000..e5a6580c8c2
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesHandlerFactory.java
@@ -0,0 +1,22 @@
+package org.intellij.sdk.language.findUsages;
+
+import com.intellij.find.findUsages.FindUsagesHandler;
+import com.intellij.find.findUsages.FindUsagesHandlerFactory;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class SdFindUsagesHandlerFactory extends FindUsagesHandlerFactory {
+
+ @Override
+ public boolean canFindUsages(@NotNull PsiElement element) {
+ return element instanceof PsiNamedElement;
+ }
+
+ @Override
+ public @Nullable FindUsagesHandler createFindUsagesHandler(@NotNull PsiElement element,
+ boolean forHighlightUsages) {
+ return new SdFindUsagesHandler(element);
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesProvider.java b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesProvider.java
new file mode 100644
index 00000000000..eaa5b43641d
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdFindUsagesProvider.java
@@ -0,0 +1,68 @@
+package org.intellij.sdk.language.findUsages;
+
+import com.intellij.lang.cacheBuilder.DefaultWordsScanner;
+import com.intellij.lang.cacheBuilder.WordsScanner;
+import com.intellij.lang.findUsages.FindUsagesProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import com.intellij.psi.tree.TokenSet;
+import org.intellij.sdk.language.SdLexerAdapter;
+import org.intellij.sdk.language.psi.SdDeclaration;
+import org.intellij.sdk.language.psi.SdIdentifier;
+import org.intellij.sdk.language.psi.SdIdentifierVal;
+import org.intellij.sdk.language.psi.SdIdentifierWithDashVal;
+import org.intellij.sdk.language.psi.SdTypes;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class SdFindUsagesProvider implements FindUsagesProvider {
+ @Nullable
+ @Override
+ public WordsScanner getWordsScanner() {
+ return new DefaultWordsScanner(new SdLexerAdapter(),
+ TokenSet.create(SdTypes.ID_REG, SdTypes.ID_WITH_DASH_REG, SdTypes.IDENTIFIER_VAL,
+ SdTypes.IDENTIFIER_WITH_DASH_VAL),
+ TokenSet.create(SdTypes.COMMENT),
+ TokenSet.create(SdTypes.STRING, SdTypes.INTEGER_REG, SdTypes.FLOAT_REG));
+ }
+
+ @Override
+ public boolean canFindUsagesFor(@NotNull PsiElement psiElement) {
+ return psiElement instanceof PsiNamedElement;
+ }
+
+ @Nullable
+ @Override
+ public String getHelpId(@NotNull PsiElement psiElement) {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public String getType(@NotNull PsiElement element) {
+ if (element instanceof SdDeclaration) {
+ return ((SdDeclaration) element).getTypeName();
+ } else {
+ return "";
+ }
+ }
+
+ @NotNull
+ @Override
+ public String getDescriptiveName(@NotNull PsiElement element) {
+ return "";
+ }
+
+ @NotNull
+ @Override
+ public String getNodeText(@NotNull PsiElement element, boolean useFullName) {
+ if (element instanceof SdIdentifierVal || element instanceof SdIdentifierWithDashVal) {
+ return ((SdIdentifier) element).getName();
+ } else if (element instanceof SdDeclaration) {
+ String fullText = element.getNode().getText();
+ return fullText.substring(0, fullText.indexOf('{'));
+ } else {
+ return "";
+ }
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdRankProfileGroupingRule.java b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdRankProfileGroupingRule.java
new file mode 100644
index 00000000000..379f70903df
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdRankProfileGroupingRule.java
@@ -0,0 +1,32 @@
+package org.intellij.sdk.language.findUsages;
+
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.psi.PsiElement;
+import com.intellij.usages.Usage;
+import com.intellij.usages.UsageGroup;
+import com.intellij.usages.UsageTarget;
+import com.intellij.usages.rules.PsiElementUsage;
+import com.intellij.usages.rules.SingleParentUsageGroupingRule;
+import org.intellij.sdk.language.SdLanguage;
+import org.intellij.sdk.language.psi.SdRankProfileDefinition;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class SdRankProfileGroupingRule extends SingleParentUsageGroupingRule implements DumbAware {
+
+ @Override
+ protected @Nullable UsageGroup getParentGroupFor(@NotNull Usage usage, UsageTarget @NotNull [] targets) {
+ PsiElement psiElement = usage instanceof PsiElementUsage ? ((PsiElementUsage)usage).getElement() : null;
+ if (psiElement == null || psiElement.getLanguage() != SdLanguage.INSTANCE) return null;
+
+ while (psiElement != null) {
+ if (psiElement instanceof SdRankProfileDefinition) {
+ final SdRankProfileDefinition componentElement = (SdRankProfileDefinition) psiElement;
+ return new SdUsageGroup(componentElement);
+ }
+ psiElement = psiElement.getParent();
+ }
+
+ return null;
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdRankProfileGroupingRuleProvider.java b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdRankProfileGroupingRuleProvider.java
new file mode 100644
index 00000000000..9ed8628dc44
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdRankProfileGroupingRuleProvider.java
@@ -0,0 +1,15 @@
+package org.intellij.sdk.language.findUsages;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.usages.impl.FileStructureGroupRuleProvider;
+import com.intellij.usages.rules.UsageGroupingRule;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class SdRankProfileGroupingRuleProvider implements FileStructureGroupRuleProvider {
+
+ @Override
+ public @Nullable UsageGroupingRule getUsageGroupingRule(@NotNull Project project) {
+ return new SdRankProfileGroupingRule();
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdUsageGroup.java b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdUsageGroup.java
new file mode 100644
index 00000000000..21f54f86472
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/findUsages/SdUsageGroup.java
@@ -0,0 +1,89 @@
+package org.intellij.sdk.language.findUsages;
+
+import com.intellij.navigation.ItemPresentation;
+import com.intellij.navigation.NavigationItemFileStatus;
+import com.intellij.openapi.util.NlsSafe;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.FileStatus;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.SmartPointerManager;
+import com.intellij.psi.SmartPsiElementPointer;
+import com.intellij.usages.UsageGroup;
+import org.intellij.sdk.language.psi.SdDeclaration;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class SdUsageGroup implements UsageGroup {
+ private final VirtualFile myFile;
+ private final SmartPsiElementPointer<SdDeclaration> myElementPointer;
+ private final String myText;
+ private final Icon myIcon;
+
+ public SdUsageGroup(SdDeclaration element) {
+ myFile = element.getContainingFile().getVirtualFile();
+ myText = StringUtil.notNullize(element.getName());
+ myElementPointer = SmartPointerManager.getInstance(element.getProject()).createSmartPsiElementPointer(element);
+ ItemPresentation presentation = element.getPresentation();
+ myIcon = presentation != null ? presentation.getIcon(true) : null;
+ }
+
+ @Override
+ public boolean isValid() {
+ SdDeclaration element = myElementPointer.getElement();
+ return element != null && element.isValid();
+ }
+
+ @Override
+ public void navigate(boolean requestFocus) {
+ final SdDeclaration nameElement = myElementPointer.getElement();
+ if (nameElement != null) {
+ nameElement.navigate(requestFocus);
+ }
+ }
+
+ @Override
+ public boolean canNavigate() {
+ return isValid();
+ }
+
+ @Override
+ public boolean canNavigateToSource() {
+ return canNavigate();
+ }
+
+ @Override
+ public int compareTo(@NotNull UsageGroup usageGroup) {
+ return getPresentableGroupText().compareToIgnoreCase(usageGroup.getPresentableGroupText());
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object instanceof SdUsageGroup) {
+ final SdUsageGroup other = (SdUsageGroup) object;
+ return myFile.equals(other.myFile) && myText.equals(other.myText);
+ }
+ return false;
+ }
+
+ @Override
+ public FileStatus getFileStatus() {
+ return isValid() ? NavigationItemFileStatus.get(myElementPointer.getElement()) : null;
+ }
+
+ @Override
+ public int hashCode() {
+ return myText.hashCode();
+ }
+
+ @Override
+ public @NotNull String getPresentableGroupText() {
+ return myText;
+ }
+
+ @Override
+ public @Nullable Icon getIcon() {
+ return myIcon;
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyBrowser.java b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyBrowser.java
new file mode 100644
index 00000000000..5960f1241c3
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyBrowser.java
@@ -0,0 +1,76 @@
+package org.intellij.sdk.language.hierarchy;
+
+import com.intellij.ide.hierarchy.CallHierarchyBrowserBase;
+import com.intellij.ide.hierarchy.HierarchyNodeDescriptor;
+import com.intellij.ide.hierarchy.HierarchyTreeStructure;
+import com.intellij.ide.util.treeView.NodeDescriptor;
+import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.ActionPlaces;
+import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.ui.PopupHandler;
+import com.intellij.util.ObjectUtils;
+import org.intellij.sdk.language.psi.SdFunctionDefinition;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Comparator;
+import java.util.Map;
+
+import javax.swing.JTree;
+
+public class SdCallHierarchyBrowser extends CallHierarchyBrowserBase {
+
+ public SdCallHierarchyBrowser(@NotNull Project project,
+ @NotNull PsiElement macro) {
+ super(project, macro);
+ }
+
+ @Nullable
+ @Override
+ protected PsiElement getElementFromDescriptor(@NotNull HierarchyNodeDescriptor descriptor) {
+ return ObjectUtils.tryCast(descriptor.getPsiElement(), PsiElement.class);
+ }
+
+ @Override
+ protected void createTrees(@NotNull Map<? super String, ? super JTree> type2TreeMap) {
+ ActionGroup group = (ActionGroup) ActionManager.getInstance().getAction(IdeActions.GROUP_CALL_HIERARCHY_POPUP);
+ type2TreeMap.put(getCallerType(), createHierarchyTree(group));
+ type2TreeMap.put(getCalleeType(), createHierarchyTree(group));
+ }
+
+ private JTree createHierarchyTree(ActionGroup group) {
+ final JTree tree = createTree(false);
+ PopupHandler.installPopupMenu(tree, group, ActionPlaces.CALL_HIERARCHY_VIEW_POPUP);
+ return tree;
+ }
+
+ @Override
+ protected boolean isApplicableElement(@NotNull PsiElement element) {
+ return element instanceof SdFunctionDefinition;
+ }
+
+
+ @Nullable
+ @Override
+ protected HierarchyTreeStructure createHierarchyTreeStructure(@NotNull String typeName, @NotNull PsiElement psiElement) {
+ if (getCallerType().equals(typeName)) {
+ return new SdCallerTreeStructure(myProject, psiElement, getCurrentScopeType());
+ }
+ else if (getCalleeType().equals(typeName)) {
+ return new SdCalleeTreeStructure(myProject, psiElement, getCurrentScopeType());
+ }
+ else {
+ return null;
+ }
+ }
+
+ @Nullable
+ @Override
+ protected Comparator<NodeDescriptor<?>> getComparator() {
+ return SdHierarchyUtil.getComparator(myProject);
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyNodeDescriptor.java b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyNodeDescriptor.java
new file mode 100644
index 00000000000..0cf612b0058
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyNodeDescriptor.java
@@ -0,0 +1,71 @@
+package org.intellij.sdk.language.hierarchy;
+
+import com.intellij.ide.hierarchy.HierarchyNodeDescriptor;
+import com.intellij.ide.util.treeView.NodeDescriptor;
+import com.intellij.navigation.ItemPresentation;
+import com.intellij.openapi.roots.ui.util.CompositeAppearance;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.psi.NavigatablePsiElement;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+
+import org.intellij.sdk.language.SdIcons;
+import org.intellij.sdk.language.SdUtil;
+import org.intellij.sdk.language.psi.SdFirstPhaseDefinition;
+import org.intellij.sdk.language.psi.SdFunctionDefinition;
+
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.Icon;
+
+public class SdCallHierarchyNodeDescriptor extends HierarchyNodeDescriptor {
+
+ public SdCallHierarchyNodeDescriptor(final NodeDescriptor parentDescriptor, @NotNull final PsiElement element, final boolean isBase) {
+ super(element.getProject(), parentDescriptor, element, isBase);
+ CompositeAppearance.DequeEnd beginning = myHighlightedText.getBeginning();
+ if (element instanceof SdFunctionDefinition) {
+ beginning.addText(SdUtil.createFunctionDescription((SdFunctionDefinition) element));
+ } else if (element instanceof SdFirstPhaseDefinition) {
+ beginning.addText(((SdFirstPhaseDefinition) element).getName());
+ } else {
+ beginning.addText(element.getText());
+ }
+ }
+
+ @Override
+ public boolean update() {
+ boolean changes = super.update();
+ final CompositeAppearance oldText = myHighlightedText;
+ myHighlightedText = new CompositeAppearance();
+ NavigatablePsiElement element = (NavigatablePsiElement)getPsiElement();
+ if (element == null) {
+ return invalidElement();
+ }
+
+ final ItemPresentation presentation = element.getPresentation();
+ if (presentation != null) {
+ myHighlightedText.getEnding().addText(presentation.getPresentableText());
+ PsiFile file = element.getContainingFile();
+ if (file != null) { // adds the file's name
+ myHighlightedText.getEnding().addText(" (" + file.getName() + ")", HierarchyNodeDescriptor.getPackageNameAttributes());
+ }
+ Icon icon = SdIcons.FILE;
+ if (element instanceof SdFunctionDefinition) {
+ icon = ((SdFunctionDefinition) element).isOverride() ? SdIcons.OVERRIDE_MACRO : SdIcons.MACRO;
+ } else if (element instanceof SdFirstPhaseDefinition) {
+ icon = SdIcons.FIRST_PHASE;
+ }
+ installIcon(icon, changes);
+ }
+
+ myName = myHighlightedText.getText();
+ if (!Comparing.equal(myHighlightedText, oldText)) {
+ changes = true;
+ }
+
+
+ return changes;
+
+ }
+
+} \ No newline at end of file
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyProvider.java b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyProvider.java
new file mode 100644
index 00000000000..44bfdca134f
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallHierarchyProvider.java
@@ -0,0 +1,66 @@
+package org.intellij.sdk.language.hierarchy;
+
+
+import com.intellij.ide.hierarchy.CallHierarchyBrowserBase;
+import com.intellij.ide.hierarchy.HierarchyBrowser;
+import com.intellij.ide.hierarchy.HierarchyProvider;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiReference;
+import org.intellij.sdk.language.SdReference;
+import org.intellij.sdk.language.SdUtil;
+import org.intellij.sdk.language.psi.SdDeclaration;
+import org.intellij.sdk.language.psi.SdFunctionDefinition;
+import org.intellij.sdk.language.psi.SdIdentifierVal;
+import org.intellij.sdk.language.psi.impl.SdPsiImplUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.project.Project;
+
+import com.intellij.psi.util.PsiTreeUtil;
+
+
+public class SdCallHierarchyProvider implements HierarchyProvider {
+
+ @Override
+ public @Nullable PsiElement getTarget(@NotNull DataContext dataContext) {
+ final Project project = CommonDataKeys.PROJECT.getData(dataContext);
+ final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
+ if (project == null || editor == null) return null;
+
+ final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+ if (file == null) {
+ return null;
+ }
+ final PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
+ if (element == null) {
+ return null;
+ }
+
+ if (element instanceof SdIdentifierVal || element.getParent() instanceof SdIdentifierVal) {
+ PsiReference ref = element instanceof SdIdentifierVal ? element.getReference() : element.getParent().getReference();
+ if (ref == null) {
+ return null;
+ }
+ PsiElement resolvedRef = ref.resolve();
+ if (resolvedRef instanceof SdFunctionDefinition) {
+ return resolvedRef;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public @NotNull HierarchyBrowser createHierarchyBrowser(@NotNull PsiElement target) {
+ return new SdCallHierarchyBrowser(target.getProject(), target);
+ }
+
+ @Override
+ public void browserActivated(@NotNull HierarchyBrowser hierarchyBrowser) {
+ ((SdCallHierarchyBrowser) hierarchyBrowser).changeView(CallHierarchyBrowserBase.getCallerType());
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallTreeStructure.java b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallTreeStructure.java
new file mode 100644
index 00000000000..fb612ed851a
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallTreeStructure.java
@@ -0,0 +1,73 @@
+package org.intellij.sdk.language.hierarchy;
+
+import com.intellij.ide.hierarchy.HierarchyNodeDescriptor;
+import com.intellij.ide.hierarchy.HierarchyTreeStructure;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.ArrayUtilRt;
+import org.intellij.sdk.language.SdUtil;
+import org.intellij.sdk.language.psi.SdFile;
+import org.intellij.sdk.language.psi.SdFunctionDefinition;
+import org.intellij.sdk.language.psi.SdIdentifierVal;
+import org.intellij.sdk.language.psi.SdRankProfileDefinition;
+import org.intellij.sdk.language.psi.impl.SdPsiImplUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+public abstract class SdCallTreeStructure extends HierarchyTreeStructure {
+ protected final String myScopeType;
+ protected final SdFile myFile;
+ protected HashMap<String, List<PsiElement>> macrosMap;
+ protected HashMap<String, HashSet<SdRankProfileDefinition>> ranksHeritageMap;
+
+ public SdCallTreeStructure(Project project, PsiElement element, String currentScopeType) {
+ super(project, new SdCallHierarchyNodeDescriptor(null, element, true));
+ myScopeType = currentScopeType;
+ myFile = (SdFile) element.getContainingFile();
+ macrosMap = SdUtil.createMacrosMap(myFile);
+ ranksHeritageMap = new HashMap<>();
+ }
+
+ @NotNull
+ protected abstract HashSet<PsiElement> getChildren(@NotNull SdFunctionDefinition element);
+
+ @Override
+ protected Object @NotNull [] buildChildren(@NotNull HierarchyNodeDescriptor descriptor) {
+ final List<SdCallHierarchyNodeDescriptor> descriptors = new ArrayList<>();
+
+ if (descriptor instanceof SdCallHierarchyNodeDescriptor) {
+ PsiElement element = descriptor.getPsiElement();
+ if (element == null) {
+ return ArrayUtilRt.EMPTY_OBJECT_ARRAY;
+ }
+ boolean isCallable = SdHierarchyUtil.isExecutable(element);
+ HierarchyNodeDescriptor nodeDescriptor = getBaseDescriptor();
+ if (!isCallable || nodeDescriptor == null) {
+ return ArrayUtilRt.EMPTY_OBJECT_ARRAY;
+ }
+
+ HashSet<PsiElement> children = getChildren((SdFunctionDefinition) element);
+
+ final HashMap<PsiElement, SdCallHierarchyNodeDescriptor> callerToDescriptorMap = new HashMap<>();
+ PsiElement baseClass = PsiTreeUtil.getParentOfType(element, SdRankProfileDefinition.class);
+
+ for (PsiElement caller : children) {
+ if (isInScope(baseClass, caller, myScopeType)) {
+ SdCallHierarchyNodeDescriptor callerDescriptor = callerToDescriptorMap.get(caller);
+ if (callerDescriptor == null) {
+ callerDescriptor = new SdCallHierarchyNodeDescriptor(descriptor, caller, false);
+ callerToDescriptorMap.put(caller, callerDescriptor);
+ descriptors.add(callerDescriptor);
+ }
+ }
+ }
+ }
+ return ArrayUtil.toObjectArray(descriptors);
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCalleeTreeStructure.java b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCalleeTreeStructure.java
new file mode 100644
index 00000000000..977d1948b81
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCalleeTreeStructure.java
@@ -0,0 +1,64 @@
+package org.intellij.sdk.language.hierarchy;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.intellij.sdk.language.SdReference;
+import org.intellij.sdk.language.psi.SdExpressionDefinition;
+import org.intellij.sdk.language.psi.SdFunctionDefinition;
+import org.intellij.sdk.language.psi.SdIdentifier;
+import org.intellij.sdk.language.psi.SdIdentifierVal;
+import org.intellij.sdk.language.psi.SdRankProfileDefinition;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+public class SdCalleeTreeStructure extends SdCallTreeStructure {
+
+ public SdCalleeTreeStructure(Project project, PsiElement element, String currentScopeType) {
+ super(project, element, currentScopeType);
+ }
+
+ @NotNull
+ @Override
+ protected HashSet<PsiElement> getChildren(@NotNull SdFunctionDefinition element) {
+ return getCallees(element, macrosMap);
+ }
+
+ private HashSet<PsiElement> getCallees(@NotNull SdFunctionDefinition macro, HashMap<String, List<PsiElement>> macrosMap) {
+ final HashSet<PsiElement> results = new HashSet<>();
+ SdExpressionDefinition expression = PsiTreeUtil.findChildOfType(macro, SdExpressionDefinition.class);
+ if (expression == null) {
+ return results;
+ }
+ for (SdIdentifier identifier : PsiTreeUtil.collectElementsOfType(expression, SdIdentifier.class)) {
+ if (macrosMap.containsKey(identifier.getName())) {
+ results.add(identifier.getReference().resolve());
+ }
+ }
+
+ SdRankProfileDefinition rankProfile = PsiTreeUtil.getParentOfType(macro, SdRankProfileDefinition.class);
+ if (rankProfile == null) {
+ return results;
+ }
+ String rankProfileName = rankProfile.getName();
+ if (!ranksHeritageMap.containsKey(rankProfileName)) {
+ ranksHeritageMap.put(rankProfileName, SdHierarchyUtil.getRankProfileChildren(myFile, rankProfile));
+ }
+
+ HashSet<SdRankProfileDefinition> inheritedRanks = ranksHeritageMap.get(rankProfileName);
+
+ for (PsiElement macroImpl : macrosMap.get(macro.getName())) {
+ if (inheritedRanks.contains(PsiTreeUtil.getParentOfType(macroImpl, SdRankProfileDefinition.class))) {
+ results.add(macroImpl);
+ }
+
+ }
+
+ return results;
+ }
+
+
+} \ No newline at end of file
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallerTreeStructure.java b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallerTreeStructure.java
new file mode 100644
index 00000000000..f6b21fc9ead
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdCallerTreeStructure.java
@@ -0,0 +1,63 @@
+package org.intellij.sdk.language.hierarchy;
+
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.intellij.sdk.language.psi.SdFirstPhaseDefinition;
+import org.intellij.sdk.language.psi.SdFunctionDefinition;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.function.Consumer;
+
+public class SdCallerTreeStructure extends SdCallTreeStructure {
+
+ private HashMap<String, HashSet<PsiElement>> macroTreeChildren;
+
+ public SdCallerTreeStructure(Project project, PsiElement element, String currentScopeType) {
+ super(project, element, currentScopeType);
+ macroTreeChildren = new HashMap<>();
+ }
+
+ @NotNull
+ @Override
+ protected HashSet<PsiElement> getChildren(@NotNull SdFunctionDefinition element) {
+ return getCallers(element, macrosMap);
+ }
+
+ private HashSet<PsiElement> getCallers(@NotNull SdFunctionDefinition macro, @NotNull HashMap<String, List<PsiElement>> macrosMap) {
+ String macroName = macro.getName();
+
+ if (macroTreeChildren.containsKey(macroName)) {
+ return macroTreeChildren.get(macroName);
+ }
+
+ HashSet<PsiElement> results = new HashSet<>();
+
+ for (PsiElement macroImpl : macrosMap.get(macroName)) {
+ SearchScope searchScope = getSearchScope(myScopeType, macroImpl);
+ ReferencesSearch.search(macroImpl, searchScope).forEach((Consumer<? super PsiReference>) r -> {
+ ProgressManager.checkCanceled();
+ PsiElement psiElement = r.getElement();
+ SdFunctionDefinition f = PsiTreeUtil.getParentOfType(psiElement, SdFunctionDefinition.class, false);
+ if (f != null && !f.getName().equals(macroName)) {
+ ContainerUtil.addIfNotNull(results, f);
+ } else {
+ SdFirstPhaseDefinition fp = PsiTreeUtil.getParentOfType(psiElement, SdFirstPhaseDefinition.class, false);
+ ContainerUtil.addIfNotNull(results, fp);
+ }
+ });
+ }
+
+ macroTreeChildren.put(macroName, results);
+ return results;
+ }
+
+} \ No newline at end of file
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdHierarchyUtil.java b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdHierarchyUtil.java
new file mode 100644
index 00000000000..b3376a85524
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/hierarchy/SdHierarchyUtil.java
@@ -0,0 +1,67 @@
+package org.intellij.sdk.language.hierarchy;
+
+import com.intellij.ide.hierarchy.HierarchyBrowserManager;
+import com.intellij.ide.util.treeView.AlphaComparator;
+import com.intellij.ide.util.treeView.NodeDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+
+import org.intellij.sdk.language.SdUtil;
+import org.intellij.sdk.language.psi.SdFile;
+import org.intellij.sdk.language.psi.SdFunctionDefinition;
+import org.intellij.sdk.language.psi.SdRankProfileDefinition;
+
+import java.util.Comparator;
+import java.util.HashSet;
+
+
+public class SdHierarchyUtil {
+
+ private static final Comparator<NodeDescriptor<?>> NODE_DESCRIPTOR_COMPARATOR = Comparator.comparingInt(NodeDescriptor::getIndex);
+
+ private SdHierarchyUtil() {
+ }
+
+ public static boolean isExecutable(PsiElement component) {
+ return component instanceof SdFunctionDefinition;
+ }
+
+ public static HashSet<SdRankProfileDefinition> getRankProfileChildren(SdFile file, SdRankProfileDefinition rankProfileTarget) {
+ HashSet<SdRankProfileDefinition> result = new HashSet<>();
+ HashSet<SdRankProfileDefinition> notResult = new HashSet<>();
+
+ for (SdRankProfileDefinition rank : PsiTreeUtil.collectElementsOfType(file, SdRankProfileDefinition.class)) {
+ if (notResult.contains(rank)) {
+ continue;
+ }
+ HashSet<SdRankProfileDefinition> tempRanks = new HashSet<>();
+ SdRankProfileDefinition curRank = rank;
+ while (curRank != null) {
+ if (curRank.getName().equals(rankProfileTarget.getName())) {
+ result.addAll(tempRanks);
+ break;
+ }
+ tempRanks.add(curRank);
+ PsiElement temp = SdUtil.getRankProfileParent(curRank);
+ curRank = temp != null ? (SdRankProfileDefinition) temp : null;
+ }
+ if (curRank == null) {
+ notResult.addAll(tempRanks);
+ }
+ }
+ return result;
+ }
+
+
+ public static Comparator<NodeDescriptor<?>> getComparator(Project project) {
+ final HierarchyBrowserManager.State state = HierarchyBrowserManager.getInstance(project).getState();
+ if (state != null && state.SORT_ALPHABETICALLY) {
+ return AlphaComparator.INSTANCE;
+ }
+ else {
+ return NODE_DESCRIPTOR_COMPARATOR;
+ }
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/parser/SdParserDefinition.java b/sd-plugin/src/main/java/org/intellij/sdk/language/parser/SdParserDefinition.java
new file mode 100644
index 00000000000..9d888a89cbf
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/parser/SdParserDefinition.java
@@ -0,0 +1,87 @@
+package org.intellij.sdk.language.parser;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.ParserDefinition;
+import com.intellij.lang.PsiParser;
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.tree.IFileElementType;
+import com.intellij.psi.tree.TokenSet;
+import org.intellij.sdk.language.SdLanguage;
+import org.intellij.sdk.language.SdLexerAdapter;
+import org.intellij.sdk.language.parser.SdParser;
+import org.intellij.sdk.language.psi.SdFile;
+import org.intellij.sdk.language.psi.SdTypes;
+import org.jetbrains.annotations.NotNull;
+
+public class SdParserDefinition implements ParserDefinition {
+ public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE);
+ public static final TokenSet COMMENTS = TokenSet.create(SdTypes.COMMENT);
+ public static final TokenSet STRINGS = TokenSet.create(SdTypes.STRING);
+
+ public static final IFileElementType FILE = new IFileElementType(SdLanguage.INSTANCE);
+
+ @NotNull
+ @Override
+ public Lexer createLexer(Project project) {
+ return new SdLexerAdapter();
+ }
+
+ @NotNull
+ @Override
+ public PsiParser createParser(final Project project) {
+ return new SdParser();
+ }
+
+ @NotNull
+ @Override
+ public TokenSet getWhitespaceTokens() {
+ return WHITE_SPACES;
+ }
+
+ @NotNull
+ @Override
+ public TokenSet getCommentTokens() {
+ return COMMENTS;
+ }
+
+ @NotNull
+ @Override
+ public TokenSet getStringLiteralElements() {
+ return STRINGS;
+ }
+
+ @NotNull
+ @Override
+ public IFileElementType getFileNodeType() {
+ return FILE;
+ }
+
+ @NotNull
+ @Override
+ public PsiFile createFile(@NotNull FileViewProvider viewProvider) {
+ return new SdFile(viewProvider);
+ }
+
+ @NotNull
+ @Override
+ public SpaceRequirements spaceExistenceTypeBetweenTokens(ASTNode left, ASTNode right) {
+ return SpaceRequirements.MAY;
+ }
+
+ @NotNull
+ @Override
+ public PsiElement createElement(ASTNode node) {
+ return SdTypes.Factory.createElement(node);
+ }
+
+}
+
+
+
+
+ \ No newline at end of file
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/parser/sd.bnf b/sd-plugin/src/main/java/org/intellij/sdk/language/parser/sd.bnf
new file mode 100644
index 00000000000..a1bc4c548a0
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/parser/sd.bnf
@@ -0,0 +1,355 @@
+{
+ parserClass="org.intellij.sdk.language.parser.SdParser" // Name and the location of the parser which will be generated.
+
+ extends="com.intellij.extapi.psi.ASTWrapperPsiElement" // All nodes will extend this class. Wraps AST node to a PSI node.
+
+ // Prefix and suffix for all generated classes
+ psiClassPrefix="Sd"
+ psiImplClassSuffix="Impl"
+
+ psiPackage="org.intellij.sdk.language.psi" // Location to be used when generating PSI classes.
+ psiImplPackage="org.intellij.sdk.language.psi.impl" // Location to be used when generating PSI implementation classes.
+
+ elementTypeHolderClass="org.intellij.sdk.language.psi.SdTypes" // Element type holder class name.
+
+ elementTypeClass="org.intellij.sdk.language.psi.SdElementType" // Class which will be used to create internal nodes.
+ tokenTypeClass="org.intellij.sdk.language.psi.SdTokenType" // Class which will be used to create leaf nodes.
+
+ psiImplUtilClass="org.intellij.sdk.language.psi.impl.SdPsiImplUtil"
+
+ extends(".*Expr")=RankingExpression // Here to deal with left-recursion that happens in expressions
+
+ tokens = [
+ ID_REG = 'regexp:[a-zA-Z_][a-zA-Z0-9_]*'
+ ID_WITH_DASH_REG = 'regexp:[a-zA-Z_][a-zA-Z0-9_-]*'
+ WHITE_SPACE = 'regexp:\s+'
+ COMMENT = 'regexp:#.*'
+ SYMBOL = 'regexp:[|:{}(),.\[\]]'
+ COMPARISON_OPERATOR = 'regexp:[<>]|(==)|(<=)|(>=)|(~=)'
+ ARITHMETIC_OPERATOR = 'regexp:[\-+*/]'
+ INTEGER_REG = 'regexp:[0-9]+'
+ FLOAT_REG = 'regexp:[0-9]+[.][0-9]+[e]?'
+ STRING = 'regexp:[\"][^\"]*[\"]'
+ WORD_REG = 'regexp:\w+'
+ ]
+}
+
+// IMPORTANT NOTE: This grammar does not enforce zero-or-one occurrences of elements (treats it like zero-to-many)
+
+SdFile ::= Schema
+Schema ::= search IdentifierVal? '{' SchemaBody '}'
+SchemaBody ::= SchemaBodyOptions* DocumentDefinition SchemaBodyOptions* // Does not support zero-or-one occurrences
+private SchemaBodyOptions ::= SchemaFieldDefinition | ImportFieldDefinition | DocumentSummaryDefinition |
+ RankProfileDefinition |
+ FieldSetDefinition | ConstantDefinition | OnnxModelDefinition | StemmingDefinition |
+ raw-as-base64-in-summary | AnnotationDefinition
+
+
+
+
+SchemaFieldDefinition ::= field IdentifierVal type FieldTypeName '{' SchemaFieldBody '}'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+
+FieldTypeName ::= "array" '<' (FieldTypeName | IdentifierVal) '>' | "weightedset" '<' SingleValueFieldTypeName '>'|
+ "map" '<' (FieldTypeName | IdentifierVal) ',' (FieldTypeName | IdentifierVal) '>' | TensorType |
+ SingleValueFieldTypeName
+private SingleValueFieldTypeName ::= "string" | "int" | "long" | "bool" | "byte" | "float" | "double" | "position" | "predicate" | "raw" | "uri" |
+ "reference" '<' IdentifierVal '>' | "annotationreference" '<' IdentifierVal '>' | IdentifierVal
+private TensorType ::= "tensor" '<' ("float" | "double" | "int8" | "bfloat16") '>' '(' TensorDimension (',' TensorDimension)* ')'
+private TensorDimension ::= WORD_REG ('{' '}') | ('[' INTEGER_REG ']')
+
+SchemaFieldBody ::= SchemaFieldBodyOptions* // Does not support zero-or-one occurrences
+SchemaFieldBodyOptions ::= SchemaFieldIndexingDefinition | AttributeDefinition | RankDefinition | IndexingRewriteState |
+ MatchDefinition | StructFieldDefinition | QueryCommandDefinition
+
+SchemaFieldIndexingDefinition ::= indexing (':' SchemaFieldIndexingStatement) | ('{' SchemaFieldIndexingStatement+ '}')
+SchemaFieldIndexingStatement ::= (input IdentifierVal) | IndexingStatement
+
+DocumentSummaryDefinition ::= document-summary IdentifierWithDashVal (inherits IdentifierWithDashVal)? '{' DocumentSummaryBody '}'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+DocumentSummaryBody ::= DocumentSummaryBodyOptions* // Does not support zero-or-one occurrences
+private DocumentSummaryBodyOptions ::= SummaryDefinition | omit-summary-features | from-disk
+
+ImportFieldDefinition ::= import field IdentifierVal '.' IdentifierVal as IdentifierVal '{''}'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+
+FieldSetDefinition ::= fieldset IdentifierVal '{' FieldSetBody '}'
+FieldSetBody ::= FieldSetBodyOptions*
+private FieldSetBodyOptions ::= (fields ':' IdentifierVal (',' IdentifierVal)*) | QueryCommandDefinition | MatchDefinition
+
+ConstantDefinition ::= constant IdentifierVal '{' ConstantBody '}'
+ConstantBody ::= ConstantBodyOptions*
+private ConstantBodyOptions ::= (file ':' FilePath) | (uri ':' UriPath) | (type ':' TensorType)
+private FilePath ::= (IdentifierVal | WORD_REG) ('.' | '/' | IdentifierWithDashVal | WORD_REG)+
+private UriPath ::= ('H'|'h') ('T'|'t') ('T'|'t') ('P'|'p') ('S'|'s')? ':' ('//')? (IdentifierWithDashVal | '.' | '/' | ':')+
+
+
+OnnxModelDefinition ::= onnx-model IdentifierVal '{' OnnxModelBody '}'
+OnnxModelBody ::= OnnxModelBodyOptions*
+private OnnxModelBodyOptions ::= (file ':' FilePath) | (uri ':' UriPath) |
+ ((input | output) (IdentifierVal | STRING) ':' ('.' | '/' | '(' | ')' | IdentifierWithDashVal | WORD_REG))
+
+AnnotationDefinition ::= annotation IdentifierVal '{' '}' // todo ask Vespa for syntax
+
+//-------------------------
+//--- Expressions rules ---
+//-------------------------
+RankingExpression ::= ParenthesisedExpr | BooleanExpr |ArithmeticExpr | IfFunctionExpr |
+ QueryDefinitionExpr | FunctionCallExpr | PrimitiveExpr //ReduceExpr |
+
+IfFunctionExpr ::= "if" '(' (InListRankingExpression | RankingExpression) ',' RankingExpression ',' RankingExpression ')'
+InListRankingExpression ::= RankingExpression "in" '[' RankingExpression (',' RankingExpression)* ']'
+
+//ReduceExpr ::= reduce '(' RankingExpression ',' (avg|count|max|median|min|prod|sum) (',' RankingExpression)* ')'
+
+BooleanExpr ::= RankingExpression COMPARISON_OPERATOR RankingExpression
+
+ArithmeticExpr ::= RankingExpression ARITHMETIC_OPERATOR RankingExpression
+
+QueryDefinitionExpr ::= QueryDefinition | ItemRawScoreDefinition
+
+FunctionCallExpr ::= IdentifierWithDashVal '(' RankingExpression (',' RankingExpression)* ')' ('.' IdentifierWithDashVal)?
+
+ParenthesisedExpr ::= '(' RankingExpression ')'
+
+PrimitiveExpr ::= (('-')? INTEGER_REG) | (('-')? FLOAT_REG) | IdentifierVal | RankFeature
+
+//-------------------------
+//-- Rank Profile rules ---
+//-------------------------
+RankProfileDefinition ::= rank-profile IdentifierWithDashVal (inherits IdentifierWithDashVal)? '{' RankProfileBody '}'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+private RankProfileBody ::= RankProfileBodyOptions* // Does not support zero-or-one occurrences
+private RankProfileBodyOptions ::= MatchPhaseDefinition | NumThreadsDefinition | FunctionDefinition | TermwiseLimitDefinition |
+ ignore-default-rank-features | RankPropertiesDefinition | FirstPhaseDefinition |
+ SummaryFeaturesDefinition | RankFeaturesDefinition | SecondPhaseDefinition | ConstantsDefinition |
+ RankDefinition | RankTypeDefinition | MinHitsDefinition | NumSearchPartitionDefinition
+ // | FieldWeightDefinition | ExecuteDefinition | RankDegradationDefinition // todo check with Vespa if need to add these
+
+MatchPhaseDefinition ::= match-phase '{' MatchPhaseBody '}'
+MatchPhaseBody ::= MatchPhaseBodyOptions+ // todo check with Vespa- are there more options?
+MatchPhaseBodyOptions ::= (attribute ':' IdentifierVal (order ':' (ascending | descending))?) | (max-hits ':' INTEGER_REG)
+ | DiversityDefinition // Does not support zero-or-one occurrences
+DiversityDefinition ::= diversity '{' (attribute ':' IdentifierVal min-groups ':' INTEGER_REG) |
+ (min-groups ':' INTEGER_REG attribute ':' IdentifierVal) '}'
+
+private NumThreadsDefinition ::= num-threads-per-search ':' INTEGER_REG
+private TermwiseLimitDefinition ::= termwise-limit ':' (FLOAT_REG | INTEGER_REG)
+private MinHitsDefinition ::= min-hits-per-thread ':' INTEGER_REG
+private NumSearchPartitionDefinition ::= num-search-partition ':' INTEGER_REG
+FirstPhaseDefinition ::= first-phase '{' FirstPhaseBody '}' { methods=[getName getPresentation] }
+FirstPhaseBody ::= FirstPhaseBodyOptions* // Does not support zero-or-one occurrences
+private FirstPhaseBodyOptions ::= (keep-rank-count ':' INTEGER_REG) | (rank-score-drop-limit ':' (FLOAT_REG | INTEGER_REG)) | ExpressionDefinition
+
+ExpressionDefinition ::= expression ((':' RankingExpression) | ('{' RankingExpression* '}') |
+ (':' file ':' FilePath))
+
+SecondPhaseDefinition ::= second-phase '{' SecondPhaseBody '}'
+SecondPhaseBody ::= SecondPhaseBodyOptions*
+private SecondPhaseBodyOptions ::= (rerank-count ':' INTEGER_REG) | ExpressionDefinition
+
+RankPropertiesDefinition ::= rank-properties '{' RankPropertiesBody '}'
+RankPropertiesBody ::= (RankPropertiesKey ':' RankPropertiesValue)+
+RankPropertiesKey ::= (IdentifierWithDashVal | STRING | '(' | ')' | '.' | ',')+
+RankPropertiesValue ::= (('-')? INTEGER_REG) | (('-')? FLOAT_REG) | WORD_REG | IdentifierVal | STRING
+
+FunctionDefinition ::= (function | macro) inline? IdentifierVal '(' (ArgumentDefinition (',' ArgumentDefinition)*)? ')'
+ '{' ExpressionDefinition '}'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation isOverride] }
+ArgumentDefinition ::= IdentifierVal
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+
+SummaryFeaturesDefinition ::= summary-features ((':' RankFeature+) | ((inherits IdentifierVal)? '{' RankFeature* '}'))
+
+RankFeaturesDefinition ::= rank-features (':' RankFeature+) | ('{' RankFeature* '}')
+
+ConstantsDefinition ::= constants '{' (IdentifierVal ':' RankPropertiesValue)* '}'
+
+//******** Rank features *********
+RankFeature ::= QueryDefinition | ItemRawScoreDefinition | FunctionCallExpr | (IdentifierWithDashVal ('.' IdentifierWithDashVal)* )
+
+QueryDefinition ::= "query" '(' IdentifierWithDashVal ')'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+ItemRawScoreDefinition ::= "itemRawScore" '(' IdentifierVal ')'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+
+// QueryFeature | DocumentFeature | QueryTermFieldMatchFeature | AttributeMatchFeature | RankScoreFeature |
+// GlobalFeature | MatchOperatorScoreFeature | UtilityFeature | RankingExpressionMethod
+ //todo add the rest (| FieldMatchFeature | QueryFieldSimilarityFeature | IdxMultiStrFieldFeature | MultiFieldsAttributesFeature)
+
+// todo maybe not specify all of the rank features here? Maybe it would be better to write it more generally? like ID '(' ID ')' '.' ID.. so it could handle new features in the future
+//QueryFeature ::= QueryDefinition | (term '(' (FLOAT_REG | INTEGER_REG) ')' '.' (significant | weight | connectedness)) // todo add queryTermCount
+//DocumentFeature ::= (fieldLength '(' IdentifierVal ')') | (attribute '(' IdentifierVal ')' ('.' count)?) |
+// (attribute '(' IdentifierVal ',' (INTEGER_REG | IdentifierVal) ')' ('.' (weight | contains))?) |
+// (tensorFromWeightedSet '(' ((attribute'('IdentifierVal')') | QueryDefinition | IdentifierVal) ',' IdentifierVal ')') |
+// (tensorFromLabels '(' ((attribute'('IdentifierVal')') | QueryDefinition | IdentifierVal) ',' IdentifierVal ')')
+//QueryTermFieldMatchFeature ::= (matchCount'('IdentifierVal')') | (matches'('IdentifierVal (',' INTEGER_REG)? ')') // todo add the rest
+//AttributeMatchFeature ::= (attributeMatch'('IdentifierVal')' ('.' (completeness | queryCompleteness | fieldCompleteness |
+// normalizedWeight | normalizedWeightedWeight | matches | totalWeight | averageWeight | maxWeight))?) |
+// (distance'('IdentifierVal')' ('.' (index | latitude | longitude))?) |
+// (distanceToPath'('IdentifierVal')' ('.' (distance | traveled | product))?) | (age'('IdentifierVal')') // todo add closeness and freshness
+//RankScoreFeature ::= (nativeDotProduct'('IdentifierVal')') // todo add the rest
+//GlobalFeature ::= (random'('IdentifierVal')' '.' match) | (random) // todo add the rest
+//MatchOperatorScoreFeature ::= (rawScore'('IdentifierVal')') | ItemRawScoreDefinition
+//UtilityFeature ::= (dotProduct'('IdentifierVal ',' IdentifierVal ')') // todo add the rest
+//RankingExpressionMethod ::= "rankingExpression" '(' (RankFeature | IdentifierVal) ')'
+//***** End of Rank features *****
+
+
+//-------------------------
+//---- Document rules -----
+//-------------------------
+DocumentDefinition ::= document (IdentifierVal (inherits IdentifierVal (',' IdentifierVal)*)?)? '{' DocumentBody '}'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+
+DocumentBody ::= DocumentBodyOptions*
+DocumentBodyOptions ::= DocumentStructDefinition | DocumentFieldDefinition
+
+DocumentStructDefinition ::= struct IdentifierVal '{' DocumentStructBody '}'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+
+DocumentStructBody ::= DocumentStructFieldDefinition*
+DocumentStructFieldDefinition ::= field IdentifierVal type FieldTypeName '{' DocumentStructFieldBody '}'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+
+DocumentStructFieldBody ::= MatchDefinition?
+
+DocumentFieldDefinition ::= field IdentifierVal type FieldTypeName '{' DocumentFieldBody '}'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+
+DocumentFieldBody ::= DocumentFieldBodyOptions* // Does not support zero-or-one occurrences
+private DocumentFieldBodyOptions ::= StructFieldDefinition | MatchDefinition | IndexingDefinition | AttributeDefinition |
+ AliasDef | RankDefinition | IndexingRewriteState | QueryCommandDefinition | SummaryDefinition |
+ BoldingDefinition | (id ':' INTEGER_REG) | IndexDefinition | (normalizing ':' IdentifierWithDashVal) |
+ SortingDefinition | StemmingDefinition | (weight ': INTEGER_REG') | WeightedSetDefinition |
+ RankTypeDefinition | DictionaryDefinition // todo check with Vespa- SummaryToDefinition is needed here? it's deprecated
+
+//***** Field's body elements ******//
+// Struct
+StructFieldDefinition ::= struct-field IdentifierVal '{' StructFieldBody '}'
+ { mixin="org.intellij.sdk.language.psi.impl.SdNamedElementImpl"
+ implements=["org.intellij.sdk.language.psi.SdDeclaration" "org.intellij.sdk.language.psi.SdNamedElement"]
+ methods=[getName setName getType getTypeName getNameIdentifier getPresentation] }
+
+StructFieldBody ::= StructFieldBodyOptions* // Does not support zero-or-one occurrences
+StructFieldBodyOptions ::= IndexingDefinition | AttributeDefinition | MatchDefinition | QueryCommandDefinition |
+ StructFieldDefinition | SummaryDefinition
+// Match
+MatchDefinition ::= match ((':' MatchProperty) | ('{' MatchProperty+ '}'))
+MatchProperty ::= text | exact | exact-terminator | word | prefix | cased | uncased | substring | suffix | max-length |
+ gram | gram-size
+// Indexing
+IndexingDefinition ::= indexing (':' IndexingStatement) | ('{' IndexingStatement+ '}')
+IndexingStatement ::= IndexingStatementOptions (('|' IndexingStatementOptions)*) | ((';' IndexingStatementOptions)*)
+ // Does not support zero-or-one occurrences // todo check with Vespa- Can "input" be here?
+IndexingStatementOptions ::= summary | attribute | index | "set_language"
+// Attribute
+AttributeDefinition ::= attribute ((':' SimpleAttributeProperty) | ('{' (SimpleAttributeProperty | ComplexAttributeProperty)+ '}'))
+SimpleAttributeProperty ::= fast-search | fast-access | paged | mutable // Does not support zero-or-one occurrences
+ComplexAttributeProperty ::= AliasDef | SortingDefinition | DistanceMetricDef // Does not support zero-or-one occurrences
+DistanceMetricDef ::= distance-metric ':' IdentifierWithDashVal
+// Alias
+AliasDef ::= alias IdentifierVal? ':' IdentifierWithDashVal
+// Stemming
+StemmingDefinition ::= stemming ':' IdentifierWithDashVal
+// Rank
+RankDefinition ::= rank ((IdentifierVal? ':' RankingSetting) | ('{' RankingSetting '}'))
+RankingSetting ::= filter | normal | literal // todo check with Vespa- is "literal" good here?
+// Indexing Rewrite
+IndexingRewriteState ::= indexing-rewrite ':' none
+// Query Command
+QueryCommandDefinition ::= query-command ':' IdentifierVal | STRING
+// Summary
+SummaryDefinition ::= summary ((':' SummaryBodyOptions) | (IdentifierWithDashVal? (type FieldTypeName)? '{' SummaryBody '}'))
+ { methods=[getName getPresentation] }
+SummaryBody ::= SummaryBodyOptions* // Does not support zero-or-one occurrences
+SummaryBodyOptions ::= full | dynamic | (source ':' IdentifierVal (',' IdentifierVal)*) |
+ (to ':' IdentifierVal (',' IdentifierVal)*) | matched-elements-only
+// Bolding
+BoldingDefinition ::= bolding ':' (on | off | true | false)
+// Index
+IndexDefinition ::= index IdentifierVal (':' IndexProperty) | ('{' IndexProperty* '}')
+IndexProperty ::= IndexPropertyOptions*
+private IndexPropertyOptions ::= (alias ':' IdentifierWithDashVal) | StemmingDefinition | (arity ':' INTEGER_REG) |
+ (lower-bound ':' INTEGER_REG ('L')?) | (upper-bound ':' INTEGER_REG ('L')?) |
+ (dense-posting-list-threshold ':' FLOAT_REG) | enable-bm25 | HnswDefinition
+HnswDefinition ::= hnsw '{' HnswBody '}'
+HnswBody ::= HnswBodyOptions*
+private HnswBodyOptions ::= (max-links-per-node ':' INTEGER_REG) | (neighbors-to-explore-at-insert ':' INTEGER_REG) |
+ (multi-threaded-indexing ':' (on | off | true | false))
+// Sorting
+SortingDefinition ::= sorting (':' SortingProperty) | ('{' SortingProperty* '}')
+SortingProperty ::= ascending | descending | (function ':' SortingFunction) | (strength ':' SortingStrength) |
+ (locale ':' IdentifierWithDashVal)
+SortingFunction ::= uca | raw | lowercase
+SortingStrength ::= primary | secondary | tertiary | quaternary | identical
+// Rank Type
+RankTypeDefinition ::= rank-type IdentifierVal ':' IdentifierVal
+// Weighted Set
+WeightedSetDefinition ::= weightedset (':' WeightedSetProperty) | ('{' WeightedSetProperty* '}') // Does not support
+ // zero-or-one occurrences
+WeightedSetProperty ::= create-if-nonexistent | remove-if-zero
+// Dictionary
+DictionaryDefinition ::= dictionary (':' DictionarySetting) | ('{' DictionarySetting* '}')
+DictionarySetting ::= hash | btree | cased | uncased
+//***** End of Field's body elements ******//
+
+//---------------------
+//---- Util rules -----
+//---------------------
+
+IdentifierVal ::= KeywordOrIdentifier | ID_REG { implements=["org.intellij.sdk.language.psi.SdIdentifier"]
+ methods=[getName setName getNameIdentifier getReference isFunctionName] }
+
+IdentifierWithDashVal ::= ID_WITH_DASH_REG | IdentifierVal { implements=["org.intellij.sdk.language.psi.SdIdentifier"]
+ methods=[getName setName getNameIdentifier getReference isFunctionName] }
+
+// Those lists of keywords (KeywordOrIdentifier and KeywordNotIdentifier) have to be synchronized with sd.flex file.
+// If you add a keyword here, you should add it to the sd.flex file as well.
+KeywordOrIdentifier ::= search | document | struct | field | type | indexing | input | output | inherits | import | as |
+ raw | uri | file | annotationreference | array | weightedset | map |
+ order | ascending | descending | diversity | constants | literal | expression | weight | match |
+ function | macro | inline | text | exact | word | prefix | cased | uncased | substring | suffix |
+ gram | paged | mutable | alias | sorting | strength | locale | uca | lowercase |
+ primary | secondary | tertiary | quaternary | identical | rank | filter | normal | none | full | dynamic |
+ source | to |
+ bolding | on | off | true | false | id | normalizing | stemming | arity | hnsw | dictionary | hash | btree |
+ fieldset | fields | constant | annotation
+ // KeywordNotIdentifier ::= (not enforced in this version)
+ | attribute | body | header | index |
+ reference | summary
+
+KeywordNotIdentifier ::= struct-field | document-summary | omit-summary-features | from-disk | rank-profile | rank-type |
+ num-threads-per-search | termwise-limit | ignore-default-rank-features | min-hits-per-thread |
+ num-search-partition | match-phase | max-hits | second-phase | rerank-count | min-groups |
+ first-phase | keep-rank-count | rank-score-drop-limit | rank-properties | summary-features |
+ exact-terminator | max-length | gram-size | fast-search | fast-access | distance-metric |
+ indexing-rewrite | query-command | matched-elements-only | lower-bound | upper-bound |
+ dense-posting-list-threshold | enable-bm25 | max-links-per-node | neighbors-to-explore-at-insert |
+ multi-threaded-indexing | create-if-nonexistent | remove-if-zero | raw-as-base64-in-summary |
+ onnx-model
+ \ No newline at end of file
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdDeclaration.java b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdDeclaration.java
new file mode 100644
index 00000000000..c46466ddb84
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdDeclaration.java
@@ -0,0 +1,14 @@
+package org.intellij.sdk.language.psi;
+
+import com.intellij.navigation.NavigationItem;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+
+public interface SdDeclaration extends PsiElement, PsiNamedElement, NavigationItem {
+ String getName();
+
+ String getTypeName();
+
+ SdDeclarationType getType();
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdDeclarationType.java b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdDeclarationType.java
new file mode 100644
index 00000000000..f832a0d01e2
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdDeclarationType.java
@@ -0,0 +1,27 @@
+package org.intellij.sdk.language.psi;
+
+public enum SdDeclarationType {
+ DOCUMENT("Document"),
+ STRUCT("Struct"),
+ SCHEMA_FIELD("Field (in Schema)"),
+ DOCUMENT_FIELD("Field (in Document)"),
+ STRUCT_FIELD("Struct-Field"),
+ DOCUMENT_STRUCT_FIELD("Field (in Struct)"),
+ IMPORTED_FIELD("Imported Field"),
+ DOCUMENT_SUMMARY("Document-Summary"),
+ RANK_PROFILE("Rank Profile"),
+ MACRO("Macro"),
+ MACRO_ARGUMENT("Macro's Argument"),
+ QUERY("Query (first use in file)"),
+ ITEM_RAW_SCORE("ItemRawScore (first use in file)");
+
+ private final String typeName;
+ SdDeclarationType(String name) {
+ this.typeName = name;
+ }
+
+ @Override
+ public String toString() {
+ return typeName;
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementDescriptionProvider.java b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementDescriptionProvider.java
new file mode 100644
index 00000000000..ea588f965e5
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementDescriptionProvider.java
@@ -0,0 +1,29 @@
+package org.intellij.sdk.language.psi;
+
+import com.intellij.psi.ElementDescriptionLocation;
+import com.intellij.psi.ElementDescriptionProvider;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import org.intellij.sdk.language.psi.SdDeclaration;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+
+public class SdElementDescriptionProvider implements ElementDescriptionProvider {
+
+ /**
+ * Controls the headline of the element in the "Find Usages" window
+ * @param psiElement the element to describe
+ * @param elementDescriptionLocation
+ * @return a string with the description to write in the headline
+ */
+ @Nullable
+ @Override
+ public String getElementDescription(@NotNull PsiElement psiElement, @NotNull ElementDescriptionLocation elementDescriptionLocation) {
+ if (psiElement instanceof SdDeclaration) {
+ return ((SdDeclaration) psiElement).getTypeName();
+ } else {
+ return "";
+ }
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementFactory.java b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementFactory.java
new file mode 100644
index 00000000000..0961704443c
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementFactory.java
@@ -0,0 +1,30 @@
+package org.intellij.sdk.language.psi;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiFileFactory;
+
+import com.intellij.psi.util.PsiTreeUtil;
+import org.intellij.sdk.language.SdFileType;
+
+public class SdElementFactory {
+
+ private static final String GENERAL_FILE_TEXT = "search {document %s {} rank-profile %s {}}";
+
+ public static SdIdentifierVal createIdentifierVal(Project project, String name) {
+ String fileText = String.format(GENERAL_FILE_TEXT, name, name);
+ final SdFile file = createFile(project, fileText);
+ return PsiTreeUtil.findChildOfType(file, SdIdentifierVal.class);
+ }
+
+ public static SdIdentifierWithDashVal createIdentifierWithDashVal(Project project, String name) {
+ String fileText = String.format(GENERAL_FILE_TEXT, name, name);
+ final SdFile file = createFile(project, fileText);
+ return PsiTreeUtil.findChildOfType(file, SdIdentifierWithDashVal.class);
+ }
+
+ public static SdFile createFile(Project project, String text) {
+ String name = "dummy.sd";
+ return (SdFile) PsiFileFactory.getInstance(project).
+ createFileFromText(name, SdFileType.INSTANCE, text);
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementType.java b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementType.java
new file mode 100644
index 00000000000..a17ae3c1c07
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdElementType.java
@@ -0,0 +1,13 @@
+package org.intellij.sdk.language.psi;
+
+import com.intellij.psi.tree.IElementType;
+import org.intellij.sdk.language.SdLanguage;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+public class SdElementType extends IElementType {
+
+ public SdElementType(@NotNull @NonNls String debugName) {
+ super(debugName, SdLanguage.INSTANCE);
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdFile.java b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdFile.java
new file mode 100644
index 00000000000..0e0a8b0661c
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdFile.java
@@ -0,0 +1,26 @@
+package org.intellij.sdk.language.psi;
+
+import com.intellij.extapi.psi.PsiFileBase;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.psi.FileViewProvider;
+import org.intellij.sdk.language.SdFileType;
+import org.intellij.sdk.language.SdLanguage;
+import org.jetbrains.annotations.NotNull;
+
+public class SdFile extends PsiFileBase {
+
+ public SdFile(@NotNull FileViewProvider viewProvider) {
+ super(viewProvider, SdLanguage.INSTANCE);
+ }
+
+ @NotNull
+ @Override
+ public FileType getFileType() {
+ return SdFileType.INSTANCE;
+ }
+
+ @Override
+ public String toString() {
+ return "Sd File";
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdIdentifier.java b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdIdentifier.java
new file mode 100644
index 00000000000..27009e9369c
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdIdentifier.java
@@ -0,0 +1,15 @@
+package org.intellij.sdk.language.psi;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import org.jetbrains.annotations.NotNull;
+
+public interface SdIdentifier extends PsiElement {
+
+ String getName();
+
+ boolean isFunctionName(PsiElement file);
+
+ @NotNull PsiReference getReference();
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdNamedElement.java b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdNamedElement.java
new file mode 100644
index 00000000000..7f4133246a0
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdNamedElement.java
@@ -0,0 +1,7 @@
+package org.intellij.sdk.language.psi;
+
+import com.intellij.psi.PsiNameIdentifierOwner;
+
+public interface SdNamedElement extends PsiNameIdentifierOwner {
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdTokenType.java b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdTokenType.java
new file mode 100644
index 00000000000..ec587ceeb86
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/SdTokenType.java
@@ -0,0 +1,18 @@
+package org.intellij.sdk.language.psi;
+
+import com.intellij.psi.tree.IElementType;
+import org.intellij.sdk.language.SdLanguage;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+public class SdTokenType extends IElementType {
+
+ public SdTokenType(@NotNull @NonNls String debugName) {
+ super(debugName, SdLanguage.INSTANCE);
+ }
+
+ @Override
+ public String toString() {
+ return "SdTokenType." + super.toString();
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/psi/impl/SdNamedElementImpl.java b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/impl/SdNamedElementImpl.java
new file mode 100644
index 00000000000..999fc4bd290
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/impl/SdNamedElementImpl.java
@@ -0,0 +1,14 @@
+package org.intellij.sdk.language.psi.impl;
+
+import com.intellij.extapi.psi.ASTWrapperPsiElement;
+import com.intellij.lang.ASTNode;
+import org.intellij.sdk.language.psi.SdNamedElement;
+import org.jetbrains.annotations.NotNull;
+
+public abstract class SdNamedElementImpl extends ASTWrapperPsiElement implements SdNamedElement {
+
+ public SdNamedElementImpl(@NotNull ASTNode node) {
+ super(node);
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/psi/impl/SdPsiImplUtil.java b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/impl/SdPsiImplUtil.java
new file mode 100644
index 00000000000..d22caa5adaa
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/psi/impl/SdPsiImplUtil.java
@@ -0,0 +1,352 @@
+package org.intellij.sdk.language.psi.impl;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.lang.ASTNode;
+import com.intellij.navigation.ItemPresentation;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.intellij.sdk.language.SdIcons;
+import org.intellij.sdk.language.SdReference;
+import org.intellij.sdk.language.SdUtil;
+import org.intellij.sdk.language.hierarchy.SdHierarchyUtil;
+import org.intellij.sdk.language.psi.SdArgumentDefinition;
+import org.intellij.sdk.language.psi.SdDeclaration;
+import org.intellij.sdk.language.psi.SdDeclarationType;
+import org.intellij.sdk.language.psi.SdDocumentDefinition;
+import org.intellij.sdk.language.psi.SdDocumentFieldDefinition;
+import org.intellij.sdk.language.psi.SdDocumentStructDefinition;
+import org.intellij.sdk.language.psi.SdDocumentStructFieldDefinition;
+import org.intellij.sdk.language.psi.SdDocumentSummaryDefinition;
+import org.intellij.sdk.language.psi.SdElementFactory;
+import org.intellij.sdk.language.psi.SdFile;
+import org.intellij.sdk.language.psi.SdFirstPhaseDefinition;
+import org.intellij.sdk.language.psi.SdIdentifier;
+import org.intellij.sdk.language.psi.SdIdentifierVal;
+import org.intellij.sdk.language.psi.SdFunctionDefinition;
+import org.intellij.sdk.language.psi.SdIdentifierWithDashVal;
+import org.intellij.sdk.language.psi.SdImportFieldDefinition;
+import org.intellij.sdk.language.psi.SdItemRawScoreDefinition;
+import org.intellij.sdk.language.psi.SdQueryDefinition;
+import org.intellij.sdk.language.psi.SdRankProfileDefinition;
+import org.intellij.sdk.language.psi.SdSchemaFieldDefinition;
+import org.intellij.sdk.language.psi.SdStructFieldDefinition;
+import org.intellij.sdk.language.psi.SdSummaryDefinition;
+import org.intellij.sdk.language.psi.SdTypes;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.Icon;
+
+/**
+ * I this class there are implementations of methods from rules in the .bnf file. While generating the psi files
+ * (classes and interfaces) the implementations would be taken from here.
+ */
+public class SdPsiImplUtil {
+
+ @NotNull
+ public static PsiReference getReference(SdIdentifier element) {
+ return new SdReference(element, new TextRange(0, element.getName().length()));
+ }
+
+ public static SdDeclarationType getType(SdDeclaration declaration) {
+ if (declaration instanceof SdSchemaFieldDefinition) {
+ return SdDeclarationType.SCHEMA_FIELD;
+ } else if (declaration instanceof SdDocumentSummaryDefinition) {
+ return SdDeclarationType.DOCUMENT_SUMMARY;
+ } else if (declaration instanceof SdImportFieldDefinition) {
+ return SdDeclarationType.IMPORTED_FIELD;
+ } else if (declaration instanceof SdRankProfileDefinition) {
+ return SdDeclarationType.RANK_PROFILE;
+ } else if (declaration instanceof SdFunctionDefinition) {
+ return SdDeclarationType.MACRO;
+ } else if (declaration instanceof SdArgumentDefinition) {
+ return SdDeclarationType.MACRO_ARGUMENT;
+ } else if (declaration instanceof SdDocumentDefinition) {
+ return SdDeclarationType.DOCUMENT;
+ } else if (declaration instanceof SdDocumentStructDefinition) {
+ return SdDeclarationType.STRUCT;
+ } else if (declaration instanceof SdDocumentStructFieldDefinition) {
+ return SdDeclarationType.DOCUMENT_STRUCT_FIELD;
+ } else if (declaration instanceof SdDocumentFieldDefinition) {
+ return SdDeclarationType.DOCUMENT_FIELD;
+ } else if (declaration instanceof SdStructFieldDefinition) {
+ return SdDeclarationType.STRUCT_FIELD;
+ } else if (declaration instanceof SdQueryDefinition) {
+ return SdDeclarationType.QUERY;
+ } else if (declaration instanceof SdItemRawScoreDefinition) {
+ return SdDeclarationType.ITEM_RAW_SCORE;
+ } else {
+ return null;
+ }
+ }
+
+ public static String getTypeName(SdDeclaration declaration) {
+ return declaration.getType().toString();
+ }
+
+ public static boolean isFunctionName(SdIdentifier identifier, PsiElement file) {
+ String name = identifier.getName();
+ for (SdFunctionDefinition macro : PsiTreeUtil.collectElementsOfType(file, SdFunctionDefinition.class)) {
+ if (name.equals(macro.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean isOverride(SdFunctionDefinition macroDeclaration) {
+ String macroName = macroDeclaration.getName();
+
+ SdRankProfileDefinition curRankProfile = PsiTreeUtil.getParentOfType(macroDeclaration, SdRankProfileDefinition.class);
+ if (curRankProfile != null) {
+ curRankProfile = (SdRankProfileDefinition) SdUtil.getRankProfileParent(curRankProfile);
+ }
+ while (curRankProfile != null) {
+ for (SdFunctionDefinition macro : PsiTreeUtil.collectElementsOfType(curRankProfile, SdFunctionDefinition.class)) {
+ if (macro.getName().equals(macroName)) {
+ return true;
+ }
+ }
+ curRankProfile = (SdRankProfileDefinition) SdUtil.getRankProfileParent(curRankProfile);
+ }
+ return false;
+
+ }
+
+ // ################################### //
+ // ##### getName implementations ##### //
+ // ################################### //
+
+ @NotNull
+ public static String getName(SdIdentifier element) {
+ if (element != null) {
+ // IMPORTANT: Convert embedded escaped spaces to simple spaces
+ return element.getText().replaceAll("\\\\ ", " ");
+ } else {
+ return "";
+ }
+ }
+
+ @NotNull
+ public static String getName(SdDeclaration declaration) {
+ ASTNode node;
+ if (declaration instanceof SdImportFieldDefinition) {
+ ASTNode asNode = declaration.getNode().findChildByType(SdTypes.AS);
+ node = declaration.getNode().findChildByType(SdTypes.IDENTIFIER_VAL, asNode);
+ } else if (declaration instanceof SdRankProfileDefinition || declaration instanceof SdDocumentSummaryDefinition
+ || declaration instanceof SdQueryDefinition) {
+ node = declaration.getNode().findChildByType(SdTypes.IDENTIFIER_WITH_DASH_VAL);
+ } else {
+ node = declaration.getNode().findChildByType(SdTypes.IDENTIFIER_VAL);
+ }
+ if (node != null) {
+ return node.getText();
+ } else {
+ return "";
+ }
+ }
+
+ @NotNull
+ public static String getName(SdSummaryDefinition summary) {
+ ASTNode node;
+ node = summary.getNode().findChildByType(SdTypes.IDENTIFIER_WITH_DASH_VAL);
+ if (node != null) {
+ return node.getText();
+ } else {
+ return "";
+ }
+ }
+
+ @NotNull
+ public static String getName(SdFirstPhaseDefinition firstPhase) {
+ SdRankProfileDefinition rankProfile = PsiTreeUtil.getParentOfType(firstPhase, SdRankProfileDefinition.class);
+ if (rankProfile == null) {
+ return "";
+ }
+ return "first-phase of " + rankProfile.getName();
+ }
+
+ // ################################### //
+ // ##### setName implementations ##### //
+ // ################################### //
+
+ @NotNull
+ public static PsiElement setName(SdIdentifierVal element, String newName) {
+ ASTNode node = element.getNode().getFirstChildNode();
+ if (node != null) {
+ SdIdentifierVal elementName = SdElementFactory.createIdentifierVal(element.getProject(), newName);
+ ASTNode newNode = elementName.getFirstChild().getNode();
+ element.getNode().replaceChild(node, newNode);
+ }
+ return element;
+ }
+
+ @NotNull
+ public static PsiElement setName(SdIdentifierWithDashVal element, String newName) {
+ ASTNode node = element.getNode().getFirstChildNode();
+ if (node != null) {
+ SdIdentifierWithDashVal elementName = SdElementFactory.createIdentifierWithDashVal(element.getProject(), newName);
+ ASTNode newNode = elementName.getFirstChild().getNode();
+ element.getNode().replaceChild(node, newNode);
+ }
+ return element;
+ }
+
+ @NotNull
+ public static PsiElement setName(SdDeclaration element, String newName) {
+ ASTNode node;
+ if (element instanceof SdImportFieldDefinition) {
+ ASTNode asNode = element.getNode().findChildByType(SdTypes.AS);
+ node = element.getNode().findChildByType(SdTypes.IDENTIFIER_VAL, asNode);
+ } else {
+ node = element.getNode().findChildByType(SdTypes.IDENTIFIER_VAL);
+ }
+ SdIdentifier elementName = null;
+ if (node != null) {
+ elementName = SdElementFactory.createIdentifierVal(element.getProject(), newName);
+ } else {
+ node = element.getNode().findChildByType(SdTypes.IDENTIFIER_WITH_DASH_VAL);
+ }
+ if (node != null) {
+ elementName = SdElementFactory.createIdentifierWithDashVal(element.getProject(), newName);
+ }
+ if (elementName != null) {
+ ASTNode newNode = elementName.getFirstChild().getNode();
+ element.getNode().replaceChild(node, newNode);
+ }
+ return element;
+ }
+
+ // ##################################### //
+ // # getNameIdentifier implementations # //
+ // ##################################### //
+
+ public static PsiElement getNameIdentifier(SdIdentifierVal element) {
+ ASTNode keyNode = element.getNode().findChildByType(SdTypes.ID);
+ if (keyNode != null) {
+ return keyNode.getPsi();
+ } else {
+ return null;
+ }
+ }
+
+ public static PsiElement getNameIdentifier(SdDeclaration element) {
+ ASTNode keyNode = element.getNode().findChildByType(SdTypes.ID);
+ if (keyNode != null) {
+ return keyNode.getPsi();
+ } else {
+ return null;
+ }
+ }
+
+ // ################################### //
+ // # getPresentation implementations # //
+ // ################################### //
+
+ public static ItemPresentation getPresentation(final SdDeclaration element) {
+ return new ItemPresentation() {
+ @Nullable
+ @Override
+ public String getPresentableText() {
+ if (element instanceof SdFunctionDefinition) {
+ return SdUtil.createFunctionDescription((SdFunctionDefinition) element);
+ }
+ SdRankProfileDefinition rankProfileParent = PsiTreeUtil.getParentOfType(element, SdRankProfileDefinition.class);
+ if (rankProfileParent != null) {
+ if (element instanceof SdQueryDefinition || element instanceof SdItemRawScoreDefinition) {
+ return element.getName() + " in " + rankProfileParent.getName();
+ }
+ return rankProfileParent.getName() + "." + element.getName();
+ }
+ return element.getName();
+ }
+
+ @Nullable
+ @Override
+ public String getLocationString() {
+ return element.getContainingFile() != null ? element.getContainingFile().getName() : null;
+ }
+
+ @Nullable
+ @Override
+ public Icon getIcon(boolean unused) {
+ if (element instanceof SdFile) {
+ return SdIcons.FILE;
+ } else if (element instanceof SdSchemaFieldDefinition || element instanceof SdDocumentFieldDefinition ||
+ element instanceof SdQueryDefinition || element instanceof SdItemRawScoreDefinition) {
+ return AllIcons.Nodes.Field;
+ } else if (element instanceof SdStructFieldDefinition ||
+ element instanceof SdDocumentStructFieldDefinition) {
+ return SdIcons.STRUCT_FIELD;
+ } else if (element instanceof SdImportFieldDefinition) {
+ return SdIcons.IMPORTED_FIELD;
+ } else if (element instanceof SdFunctionDefinition) {
+ return AllIcons.Nodes.Method;
+ // Didn't use isOverride() here because it causes the Structure View to load too slow
+ // return ((SdFunctionDefinition) element).isOverride() ? SdIcons.OVERRIDE_MACRO : AllIcons.Nodes.Method;
+ } else if (element instanceof SdDocumentStructDefinition) {
+ return SdIcons.STRUCT;
+ } else if (element instanceof SdRankProfileDefinition) {
+ return AllIcons.Nodes.Record;
+ } else if (element instanceof SdDocumentSummaryDefinition) {
+ return SdIcons.DOCUMENT_SUMMARY;
+ } else if (element instanceof SdDocumentDefinition) {
+ return SdIcons.DOCUMENT;
+ }
+ else {
+ return null;
+ }
+ }
+ };
+ }
+
+ public static ItemPresentation getPresentation(final SdSummaryDefinition element) {
+ return new ItemPresentation() {
+
+ @Override
+ public String getPresentableText() {
+ return element.getName();
+ }
+
+ @Nullable
+ @Override
+ public String getLocationString() {
+ return element.getContainingFile() != null ? element.getContainingFile().getName() : null;
+ }
+
+ @Override
+ public Icon getIcon(boolean unused) {
+ return SdIcons.SUMMARY;
+ }
+ };
+ }
+
+ public static ItemPresentation getPresentation(final SdFirstPhaseDefinition element) {
+ return new ItemPresentation() {
+
+ @Override
+ public String getPresentableText() {
+ SdRankProfileDefinition rankProfile = PsiTreeUtil.getParentOfType(element, SdRankProfileDefinition.class);
+ if (rankProfile == null) {
+ return "";
+ }
+ return "first-phase of " + rankProfile.getName();
+ }
+
+ @Nullable
+ @Override
+ public String getLocationString() {
+ return element.getContainingFile() != null ? element.getContainingFile().getName() : null;
+ }
+
+ @Override
+ public Icon getIcon(boolean unused) {
+ return SdIcons.FIRST_PHASE;
+ }
+ };
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/sd.flex b/sd-plugin/src/main/java/org/intellij/sdk/language/sd.flex
new file mode 100644
index 00000000000..c657af4f658
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/sd.flex
@@ -0,0 +1,202 @@
+package org.intellij.sdk.language.lexer;
+
+import com.intellij.lexer.FlexLexer;
+import com.intellij.psi.tree.IElementType;import com.intellij.ui.components.MultiColumnList;import org.intellij.sdk.language.psi.SdTokenType;
+
+import static com.intellij.psi.TokenType.BAD_CHARACTER; // Pre-defined bad character token.
+import static com.intellij.psi.TokenType.WHITE_SPACE; // Pre-defined whitespace character token.
+import static org.intellij.sdk.language.psi.SdTypes.*; // That is the class which is specified as `elementTypeHolderClass` in bnf
+ // grammar file. This will contain all other tokens which we will use.
+
+%%
+
+%public
+%class SdLexer
+%implements FlexLexer
+%function advance
+%type IElementType
+%unicode
+
+//**--------- REGEXES ---------**//
+// If some character sequence is matched to this regex, it will be treated as an IDENTIFIER.
+ID=[a-zA-Z_][a-zA-Z0-9_]*
+ID_WITH_DASH = [a-zA-Z_][a-zA-Z0-9_-]*
+// If some character sequence is matched to this regex, it will be treated as a WHITE_SPACE.
+WHITE_SPACE=[ \t\n\x0B\f\r]+
+
+COMMENT=#.*
+SYMBOL= [|:{}(),.\[\]]
+INTEGER = [0-9]+
+FLOAT = {INTEGER}[.][0-9]+[e]?
+COMPARISON_OPERATOR = [<>]|(==)|(<=)|(>=)|(\~=)
+ARITHMETIC_OPERATOR = [\-+*/]
+STRING = [\"][^\"\n]*[\"]
+WORD = \w+
+
+
+%%
+
+<YYINITIAL> {
+ // In here, we match keywords. So if a keyword is found, this returns a token which corresponds to that keyword.
+ // These tokens are generated using the 'sd.bnf' file and located in the SdTypes class.
+ // These tokens are Parsed uses these return values to match token squence to a parser rule.
+
+ "search" { return SEARCH; }
+ "document" { return DOCUMENT; }
+ "inherits" { return INHERITS; }
+ "struct" { return STRUCT; }
+ "field" { return FIELD; }
+ "type" { return TYPE; }
+ "struct-field" { return STRUCT_FIELD; }
+ "match" { return MATCH; }
+
+ "indexing" { return INDEXING; }
+ "summary" { return SUMMARY; }
+ "attribute" { return ATTRIBUTE; }
+
+ "array" { return ARRAY; }
+ "raw" { return RAW; }
+ "uri" { return URI; }
+ "reference" { return REFERENCE; }
+ "annotationreference" { return ANNOTATIONREFERENCE; }
+ "weightedset" { return WEIGHTEDSET; }
+ "map" { return MAP; }
+
+ "text" { return TEXT; }
+ "exact" { return EXACT; }
+ "exact-terminator" { return EXACT_TERMINATOR; }
+ "word" { return WORD; }
+ "prefix" { return PREFIX; }
+ "cased" { return CASED; }
+ "uncased" { return UNCASED; }
+ "substring" { return SUBSTRING; }
+ "suffix" { return SUFFIX; }
+ "max-length" { return MAX_LENGTH; }
+ "gram" { return GRAM; }
+ "gram-size" { return GRAM_SIZE; }
+
+ "fast-search" { return FAST_SEARCH; }
+ "fast-access" { return FAST_ACCESS; }
+ "alias" { return ALIAS; }
+ "sorting" { return SORTING; }
+ "uca" { return UCA; }
+ "lowercase" { return LOWERCASE; }
+ "paged" { return PAGED; }
+ "strength" { return STRENGTH; }
+ "primary" { return PRIMARY; }
+ "secondary" { return SECONDARY; }
+ "tertiary" { return TERTIARY; }
+ "quaternary" { return QUATERNARY; }
+ "identical" { return IDENTICAL; }
+ "distance-metric" { return DISTANCE_METRIC; }
+
+ "rank" { return RANK; }
+ "filter" { return FILTER; }
+ "normal" { return NORMAL; }
+ "indexing-rewrite" { return INDEXING_REWRITE; }
+ "none" { return NONE; }
+ "query-command" { return QUERY_COMMAND; }
+ "full" { return FULL; }
+ "dinamic" { return DYNAMIC; }
+ "source" { return SOURCE; }
+ "to" { return TO; }
+ "matched-elements-only" { return MATCHED_ELEMENTS_ONLY; }
+
+ "input" { return INPUT; }
+ "mutable" { return MUTABLE; }
+ "document-summary" { return DOCUMENT_SUMMARY; }
+ "from-disk" { return FROM_DISK; }
+ "omit-summary-features" { return OMIT_SUMMARY_FEATURES; }
+ "import" { return IMPORT; }
+ "as" { return AS; }
+
+ "rank-profile" { return RANK_PROFILE; }
+ "match-phase" { return MATCH_PHASE; }
+ "order" { return ORDER; }
+ "ascending" { return ASCENDING; }
+ "descending" { return DESCENDING; }
+ "max-hits" { return MAX_HITS; }
+ "diversity" { return DIVERSITY; }
+ "min-groups" { return MIN_GROUPS; }
+ "rank-properties" { return RANK_PROPERTIES; }
+
+ "first-phase" { return FIRST_PHASE; }
+ "keep-rank-count" { return KEEP_RANK_COUNT; }
+ "rank-score-drop-limit" { return RANK_SCORE_DROP_LIMIT; }
+ "expression" { return EXPRESSION; }
+ "file" { return FILE; }
+ "expression" { return EXPRESSION; }
+ "num-threads-per-search" { return NUM_THREADS_PER_SEARCH; }
+ "termwise-limit" { return TERMWISE_LIMIT; }
+ "ignore-default-rank-features" { return IGNORE_DEFAULT_RANK_FEATURES; }
+ "min-hits-per-thread" { return MIN_HITS_PER_THREAD; }
+ "num-search-partition" { return NUM_SEARCH_PARTITION; }
+ "constants" { return CONSTANTS; }
+ "literal" { return LITERAL; }
+ "second-phase" { return SECOND_PHASE; }
+ "rerank-count" { return RERANK_COUNT; }
+
+ "weight" { return WEIGHT; }
+ "index" { return INDEX; }
+ "bolding" { return BOLDING; }
+ "on" { return ON; }
+ "off" { return OFF; }
+ "true" { return TRUE; }
+ "false" { return FALSE; }
+ "id" { return ID; }
+ "normalizing" { return NORMALIZING; }
+ "stemming" { return STEMMING; }
+ "arity" { return ARITY; }
+ "lower-bound" { return LOWER_BOUND; }
+ "upper-bound" { return UPPER_BOUND; }
+ "dense-posting-list-threshold" {return DENSE_POSTING_LIST_THRESHOLD; }
+ "enable-bm25" { return ENABLE_BM25; }
+ "hnsw" { return HNSW; }
+ "max-links-per-node" { return MAX_LINKS_PER_NODE; }
+ "neighbors-to-explore-at-insert" { return NEIGHBORS_TO_EXPLORE_AT_INSERT; }
+ "multi-threaded-indexing" { return MULTI_THREADED_INDEXING; }
+ "create-if-nonexistent" { return CREATE_IF_NONEXISTENT; }
+ "remove-if-zero" { return REMOVE_IF_ZERO; }
+ "dictionary" { return DICTIONARY; }
+ "hash" { return HASH; }
+ "btree" { return BTREE; }
+
+ "fieldset" { return FIELDSET; }
+ "fields" { return FIELDS; }
+ "constant" { return CONSTANT; }
+ "output" { return OUTPUT; }
+
+ "annotation" { return ANNOTATION; }
+ "rank-type" { return RANK_TYPE; }
+ "onnx-model" { return ONNX_MODEL; }
+ "raw-as-base64-in-summary" { return RAW_AS_BASE64_IN_SUMMARY; }
+
+ "function" { return FUNCTION; }
+ "macro" { return MACRO; }
+ "inline" { return INLINE; }
+
+ "summary-features" { return SUMMARY_FEATURES; }
+
+ "body" { return BODY; }
+ "header" { return HEADER; }
+
+ // In here, we check for character sequences which matches regular expressions defined above.
+ {ID} { return ID_REG; }
+ {ID_WITH_DASH} { return ID_WITH_DASH_REG; }
+
+ {WHITE_SPACE} { return WHITE_SPACE; }
+
+ {COMMENT} { return COMMENT; }
+ {SYMBOL} { return SYMBOL; }
+ {INTEGER} { return INTEGER_REG; }
+ {FLOAT} { return FLOAT_REG; }
+ {ARITHMETIC_OPERATOR} { return ARITHMETIC_OPERATOR; }
+ {COMPARISON_OPERATOR} { return COMPARISON_OPERATOR; }
+ {WORD} { return WORD_REG; }
+ {STRING} { return STRING; }
+
+}
+
+// If the character sequence does not match any of the above rules, we return BAD_CHARACTER which indicates that
+// there is an error in the character sequence. This is used to highlight errors.
+[^] { return BAD_CHARACTER; } \ No newline at end of file
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewElement.java b/sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewElement.java
new file mode 100644
index 00000000000..a5f45e6b26b
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewElement.java
@@ -0,0 +1,84 @@
+package org.intellij.sdk.language.structure;
+
+import com.intellij.ide.projectView.PresentationData;
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.util.treeView.smartTree.SortableTreeElement;
+import com.intellij.ide.util.treeView.smartTree.TreeElement;
+import com.intellij.navigation.ItemPresentation;
+import com.intellij.psi.NavigatablePsiElement;
+import com.intellij.psi.PsiElement;
+import org.intellij.sdk.language.SdUtil;
+import org.intellij.sdk.language.psi.SdDocumentDefinition;
+import org.intellij.sdk.language.psi.SdDocumentStructDefinition;
+import org.intellij.sdk.language.psi.SdDocumentSummaryDefinition;
+import org.intellij.sdk.language.psi.SdFile;
+import org.intellij.sdk.language.psi.SdRankProfileDefinition;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SdStructureViewElement implements StructureViewTreeElement, SortableTreeElement {
+
+ private final NavigatablePsiElement myElement;
+
+ public SdStructureViewElement(NavigatablePsiElement element) {
+ this.myElement = element;
+ }
+
+ @Override
+ public Object getValue() {
+ return myElement;
+ }
+
+ @Override
+ public void navigate(boolean requestFocus) {
+ myElement.navigate(requestFocus);
+ }
+
+ @Override
+ public boolean canNavigate() {
+ return myElement.canNavigate();
+ }
+
+ @Override
+ public boolean canNavigateToSource() {
+ return myElement.canNavigateToSource();
+ }
+
+ @NotNull
+ @Override
+ public String getAlphaSortKey() {
+ String name = myElement.getName();
+ return name != null ? name : "";
+ }
+
+ @NotNull
+ @Override
+ public ItemPresentation getPresentation() {
+ ItemPresentation presentation = myElement.getPresentation();
+ return presentation != null ? presentation : new PresentationData();
+ }
+
+ @Override
+ public TreeElement @NotNull [] getChildren() {
+ List<PsiElement> children = new ArrayList<>();;
+ if (myElement instanceof SdFile) {
+ children = SdUtil.findSchemaChildren(myElement);
+ } else if (myElement instanceof SdDocumentDefinition) {
+ children = SdUtil.findDocumentChildren(myElement);
+ } else if (myElement instanceof SdDocumentStructDefinition) {
+ children = SdUtil.findDocumentStructChildren(myElement);
+ } else if (myElement instanceof SdRankProfileDefinition) {
+ children = SdUtil.findRankProfileChildren(myElement);
+ } else if (myElement instanceof SdDocumentSummaryDefinition) {
+ children = SdUtil.findDocumentSummaryChildren(myElement);
+ }
+
+ List<TreeElement> treeElements = new ArrayList<>(children.size());
+ for (PsiElement child : children) {
+ treeElements.add(new SdStructureViewElement((NavigatablePsiElement) child));
+ }
+ return treeElements.toArray(new TreeElement[0]);
+ }
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewFactory.java b/sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewFactory.java
new file mode 100644
index 00000000000..05590362fcf
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewFactory.java
@@ -0,0 +1,26 @@
+package org.intellij.sdk.language.structure;
+
+import com.intellij.ide.structureView.StructureViewBuilder;
+import com.intellij.ide.structureView.StructureViewModel;
+import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
+import com.intellij.lang.PsiStructureViewFactory;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class SdStructureViewFactory implements PsiStructureViewFactory {
+
+ @Nullable
+ @Override
+ public StructureViewBuilder getStructureViewBuilder(@NotNull final PsiFile psiFile) {
+ return new TreeBasedStructureViewBuilder() {
+ @NotNull
+ @Override
+ public StructureViewModel createStructureViewModel(@Nullable Editor editor) {
+ return new SdStructureViewModel(psiFile);
+ }
+ };
+ }
+
+}
diff --git a/sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewModel.java b/sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewModel.java
new file mode 100644
index 00000000000..549bd811dcf
--- /dev/null
+++ b/sd-plugin/src/main/java/org/intellij/sdk/language/structure/SdStructureViewModel.java
@@ -0,0 +1,31 @@
+package org.intellij.sdk.language.structure;
+
+import com.intellij.ide.structureView.StructureViewModel;
+import com.intellij.ide.structureView.StructureViewModelBase;
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.util.treeView.smartTree.Sorter;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+
+public class SdStructureViewModel extends StructureViewModelBase implements StructureViewModel.ElementInfoProvider {
+ public SdStructureViewModel(PsiFile psiFile) {
+ super(psiFile, new SdStructureViewElement(psiFile));
+ }
+
+
+ public Sorter @NotNull [] getSorters() {
+ return new Sorter[]{Sorter.ALPHA_SORTER};
+ }
+
+
+ @Override
+ public boolean isAlwaysShowsPlus(StructureViewTreeElement element) {
+ return false;
+ }
+
+ @Override
+ public boolean isAlwaysLeaf(StructureViewTreeElement element) {
+ return false;
+ }
+
+}