aboutsummaryrefslogtreecommitdiffstats
path: root/sd-plugin/src/main/java/org/intellij/sdk/language/SdUtil.java
diff options
context:
space:
mode:
Diffstat (limited to 'sd-plugin/src/main/java/org/intellij/sdk/language/SdUtil.java')
-rw-r--r--sd-plugin/src/main/java/org/intellij/sdk/language/SdUtil.java213
1 files changed, 213 insertions, 0 deletions
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));
+ }
+
+
+}