From 68b25042001c8779ec244762f4f98b393783064a Mon Sep 17 00:00:00 2001
From: Johannes Mey <johannes.mey@tu-dresden.de>
Date: Sun, 27 Dec 2020 12:41:36 +0100
Subject: [PATCH] extract analysis code and create line marker for nonterminal
 usages

---
 .../tooling/RelAstGrammarAnnotator.java       | 52 +++--------------
 .../RelAstGrammarLineMarkerProvider.java      | 49 +++++++---------
 .../jastadd/tooling/RelAstGrammarUtil.java    | 58 +++++++++++++++++--
 src/main/resources/META-INF/plugin.xml        |  3 +
 4 files changed, 83 insertions(+), 79 deletions(-)

diff --git a/src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java b/src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java
index 026ea61..a103a37 100644
--- a/src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java
+++ b/src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java
@@ -6,63 +6,31 @@ import com.intellij.lang.annotation.AnnotationHolder;
 import com.intellij.lang.annotation.Annotator;
 import com.intellij.lang.annotation.HighlightSeverity;
 import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
-import com.intellij.psi.JavaResolveResult;
 import com.intellij.psi.PsiClass;
 import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiJavaCodeReferenceElement;
 import com.intellij.psi.javadoc.PsiDocComment;
 import com.intellij.psi.javadoc.PsiDocTag;
-import org.jastadd.tooling.psi.RelAstGrammarTypeDecl;
 import org.jetbrains.annotations.NotNull;
 
 import java.util.Arrays;
-import java.util.List;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
+import static org.jastadd.tooling.RelAstGrammarUtil.asReferenceToTypeDecl;
+
 public class RelAstGrammarAnnotator implements Annotator {
 
   @Override
   public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
 
+    Optional<PsiClass> classOptional = asReferenceToTypeDecl(element);
 
-    // Ensure the Psi Element is an reference
-    if (!(element instanceof PsiJavaCodeReferenceElement)) {
-      return;
-    }
-
-
-    // Ensure the Psi element references something with a name
-    PsiJavaCodeReferenceElement javaCodeReferenceElement = (PsiJavaCodeReferenceElement) element;
-    String value = javaCodeReferenceElement.getReferenceName();
-    if (value == null) {
+    if (classOptional.isEmpty()) {
       return;
     }
 
-    // Ensure that the reference is valid and accessible
-    JavaResolveResult result = javaCodeReferenceElement.advancedResolve(true);
-    if (!result.isValidResult() || !result.isAccessible() || result.getElement() == null) {
-      return;
-    }
-
-    // Ensure that the reference is a Java class
-    PsiElement reference = result.getElement();
-    if (!(reference instanceof PsiClass)) {
-      return;
-    }
-
-    // Ensure that the class has a doc comment which contains the tag ast with the value node
-    PsiClass refClass = (PsiClass) reference;
-    PsiDocComment docComment = refClass.getDocComment();
-    if (docComment == null) {
-      return;
-    }
-    PsiDocTag astTag = docComment.findTagByName("ast");
-    if (astTag == null) {
-      return;
-    }
-    if (astTag.getValueElement() == null || !astTag.getValueElement().getText().equals("node")) {
-      return;
-    }
+    PsiDocComment docComment = classOptional.get().getDocComment();
+    assert docComment != null; // asReferenceToTypeDecl ensures this is not null
 
     PsiDocTag declaredAtTag = docComment.findTagByName("declaredat");
     if (declaredAtTag == null) {
@@ -82,12 +50,6 @@ public class RelAstGrammarAnnotator implements Annotator {
       .textAttributes(DefaultLanguageHighlighterColors.HIGHLIGHTED_REFERENCE)
       .tooltip("<b>JastAdd Nonterminal</b><br/>Production: <i>" + production + "</i><br/><i>Declared at </i>" + declaredAt)
       .create();
-
-    // Get the list of typeDecls for given key
-    List<RelAstGrammarTypeDecl> typeDecls = RelAstGrammarUtil.findTypeDecl(element.getProject(), value);
-    if (!typeDecls.isEmpty()) {
-      // TODO decide what to do here
-    }
   }
 
 }
diff --git a/src/main/java/org/jastadd/tooling/RelAstGrammarLineMarkerProvider.java b/src/main/java/org/jastadd/tooling/RelAstGrammarLineMarkerProvider.java
index c134114..a5ed753 100644
--- a/src/main/java/org/jastadd/tooling/RelAstGrammarLineMarkerProvider.java
+++ b/src/main/java/org/jastadd/tooling/RelAstGrammarLineMarkerProvider.java
@@ -1,47 +1,38 @@
 package org.jastadd.tooling;
 
 import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo;
-  import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider;
-  import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
-  import com.intellij.openapi.project.Project;
-  import com.intellij.psi.PsiElement;
-  import com.intellij.psi.PsiLiteralExpression;
-  import com.intellij.psi.impl.source.tree.java.PsiJavaTokenImpl;
-  import org.jetbrains.annotations.NotNull;
+import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider;
+import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import org.jastadd.tooling.psi.RelAstGrammarTypeDecl;
+import org.jetbrains.annotations.NotNull;
 
-  import java.util.Collection;
-  import java.util.List;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+import static org.jastadd.tooling.RelAstGrammarUtil.asReferenceToTypeDecl;
 
 public class RelAstGrammarLineMarkerProvider extends RelatedItemLineMarkerProvider {
 
   @Override
   protected void collectNavigationMarkers(@NotNull PsiElement element,
                                           @NotNull Collection<? super RelatedItemLineMarkerInfo<?>> result) {
-    // This must be an element with a literal expression as a parent
-    if (!(element instanceof PsiJavaTokenImpl) || !(element.getParent() instanceof PsiLiteralExpression)) {
-      return;
-    }
 
-    // The literal expression must start with the Simple language literal expression
-    PsiLiteralExpression literalExpression = (PsiLiteralExpression) element.getParent();
-    String value = literalExpression.getValue() instanceof String ? (String) literalExpression.getValue() : null;
-    if ((value == null) ||
-      !value.startsWith(SimpleAnnotator.SIMPLE_PREFIX_STR + SimpleAnnotator.SIMPLE_SEPARATOR_STR)) {
+    Optional<PsiClass> classOptional = asReferenceToTypeDecl(element);
+
+    if (classOptional.isEmpty()) {
       return;
     }
 
-    // Get the Simple language property usage
-    Project project = element.getProject();
-    String possibleProperties = value.substring(
-      SimpleAnnotator.SIMPLE_PREFIX_STR.length() + SimpleAnnotator.SIMPLE_SEPARATOR_STR.length()
-    );
-    final List<SimpleProperty> properties = SimpleUtil.findProperties(project, possibleProperties);
-    if (properties.size() > 0) {
-      // Add the property to a collection of line marker info
+    // Get the list of typeDecls for given key
+    List<RelAstGrammarTypeDecl> typeDecls = RelAstGrammarUtil.findTypeDecl(element.getProject(), classOptional.get().getName());
+    if (!typeDecls.isEmpty()) {
       NavigationGutterIconBuilder<PsiElement> builder =
-        NavigationGutterIconBuilder.create(SimpleIcons.FILE)
-          .setTargets(properties)
-          .setTooltipText("Navigate to Simple language property");
+        NavigationGutterIconBuilder.create(JastAddIcons.FILE)
+          .setTargets(typeDecls)
+          .setTooltipText("Navigate to production rule for RelAst nonterminal");
       result.add(builder.createLineMarkerInfo(element));
     }
   }
diff --git a/src/main/java/org/jastadd/tooling/RelAstGrammarUtil.java b/src/main/java/org/jastadd/tooling/RelAstGrammarUtil.java
index 37b37fc..fe5c59b 100644
--- a/src/main/java/org/jastadd/tooling/RelAstGrammarUtil.java
+++ b/src/main/java/org/jastadd/tooling/RelAstGrammarUtil.java
@@ -1,19 +1,24 @@
 package org.jastadd.tooling;
 
 
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.lang.annotation.AnnotationHolder;
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiManager;
+import com.intellij.psi.*;
+import com.intellij.psi.javadoc.PsiDocComment;
+import com.intellij.psi.javadoc.PsiDocTag;
 import com.intellij.psi.search.FileTypeIndex;
 import com.intellij.psi.search.GlobalSearchScope;
 import com.intellij.psi.util.PsiTreeUtil;
 import org.jastadd.tooling.psi.RelAstGrammarFile;
 import org.jastadd.tooling.psi.RelAstGrammarTypeDecl;
+import org.jetbrains.annotations.NotNull;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 
 public class RelAstGrammarUtil {
@@ -71,4 +76,47 @@ public class RelAstGrammarUtil {
     return result;
   }
 
+  public static Optional<PsiClass> asReferenceToTypeDecl(@NotNull final PsiElement element) {
+
+    // Ensure the Psi Element is an reference
+    if (!(element instanceof PsiJavaCodeReferenceElement)) {
+      return Optional.empty();
+    }
+
+    // Ensure the Psi element references something with a name
+    PsiJavaCodeReferenceElement javaCodeReferenceElement = (PsiJavaCodeReferenceElement) element;
+    String value = javaCodeReferenceElement.getReferenceName();
+    if (value == null) {
+      return Optional.empty();
+    }
+
+    // Ensure that the reference is valid and accessible
+    JavaResolveResult result = javaCodeReferenceElement.advancedResolve(true);
+    if (!result.isValidResult() || !result.isAccessible() || result.getElement() == null) {
+      return Optional.empty();
+    }
+
+    // Ensure that the reference is a Java class
+    PsiElement reference = result.getElement();
+    if (!(reference instanceof PsiClass)) {
+      return Optional.empty();
+    }
+
+    // Ensure that the class has a doc comment which contains the tag ast with the value node
+    PsiClass refClass = (PsiClass) reference;
+    PsiDocComment docComment = refClass.getDocComment();
+    if (docComment == null) {
+      return Optional.empty();
+    }
+    PsiDocTag astTag = docComment.findTagByName("ast");
+    if (astTag == null) {
+      return Optional.empty();
+    }
+    if (astTag.getValueElement() == null || !astTag.getValueElement().getText().equals("node")) {
+      return Optional.empty();
+    }
+
+    return Optional.of(refClass);
+  }
+
 }
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
index c1886d9..ce9e6d9 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -24,6 +24,9 @@
         <colorSettingsPage implementation="org.jastadd.tooling.RelAstGrammarColorSettingsPage"/>
 
         <annotator language="JAVA" implementationClass="org.jastadd.tooling.RelAstGrammarAnnotator"/>
+
+        <codeInsight.lineMarkerProvider language="JAVA"
+                                        implementationClass="org.jastadd.tooling.RelAstGrammarLineMarkerProvider"/>
     </extensions>
 
     <actions>
-- 
GitLab