From f8d10017a5c94da878461ecb10fd09a83f1433eb Mon Sep 17 00:00:00 2001 From: Johannes Mey <johannes.mey@tu-dresden.de> Date: Sun, 27 Dec 2020 01:55:25 +0100 Subject: [PATCH] add annotation and improve grammar to fix analysis --- build.gradle | 1 + src/main/grammar/RelAstGrammar.bnf | 4 +- .../tooling/RelAstGrammarAnnotator.java | 93 +++++++++++++++++++ .../RelAstGrammarLineMarkerProvider.java | 49 ++++++++++ src/main/resources/META-INF/plugin.xml | 3 + 5 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java create mode 100644 src/main/java/org/jastadd/tooling/RelAstGrammarLineMarkerProvider.java diff --git a/build.gradle b/build.gradle index 05dd596..50f4f19 100644 --- a/build.gradle +++ b/build.gradle @@ -32,6 +32,7 @@ dependencies { // See https://github.com/JetBrains/gradle-intellij-plugin/ intellij { version = "2020.2.4" + plugins = ['java'] } diff --git a/src/main/grammar/RelAstGrammar.bnf b/src/main/grammar/RelAstGrammar.bnf index e024246..0074794 100644 --- a/src/main/grammar/RelAstGrammar.bnf +++ b/src/main/grammar/RelAstGrammar.bnf @@ -15,9 +15,7 @@ psiImplUtilClass="org.jastadd.tooling.psi.impl.RelAstGrammarPsiImplUtil" } -relAstGrammarFile ::= comment* declaration* - -declaration ::= (type_decl | relation) comment* +relAstGrammarFile ::= comment* ((type_decl | relation) comment*)* comment ::= (WHITESPACE | MULTILINECOMMENT | DOCCOMMENT | SINGLELINECOMMENT) diff --git a/src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java b/src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java new file mode 100644 index 0000000..026ea61 --- /dev/null +++ b/src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java @@ -0,0 +1,93 @@ +package org.jastadd.tooling; + + +import com.intellij.codeInspection.ProblemHighlightType; +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.stream.Collectors; + +public class RelAstGrammarAnnotator implements Annotator { + + @Override + public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) { + + + // 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) { + 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; + } + + PsiDocTag declaredAtTag = docComment.findTagByName("declaredat"); + if (declaredAtTag == null) { + return; + } + String declaredAt = Arrays.stream(declaredAtTag.getDataElements()).map(PsiElement::getText).collect(Collectors.joining()); + + PsiDocTag productionTag = docComment.findTagByName("astdecl"); + if (productionTag == null) { + return; + } + String production = Arrays.stream(productionTag.getDataElements()).map(PsiElement::getText).collect(Collectors.joining()); + + holder.newAnnotation(HighlightSeverity.INFORMATION, "JastAdd Nonterminal: " + production) + .range(element.getTextRange()) + .highlightType(ProblemHighlightType.INFORMATION) + .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 new file mode 100644 index 0000000..c134114 --- /dev/null +++ b/src/main/java/org/jastadd/tooling/RelAstGrammarLineMarkerProvider.java @@ -0,0 +1,49 @@ +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 java.util.Collection; + import java.util.List; + +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)) { + 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 + NavigationGutterIconBuilder<PsiElement> builder = + NavigationGutterIconBuilder.create(SimpleIcons.FILE) + .setTargets(properties) + .setTooltipText("Navigate to Simple language property"); + result.add(builder.createLineMarkerInfo(element)); + } + } + +} diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index de4f7b6..c1886d9 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -10,6 +10,7 @@ <!-- please see https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html on how to target different products --> <depends>com.intellij.modules.platform</depends> + <depends>com.intellij.modules.java</depends> <extensions defaultExtensionNs="com.intellij"> <!-- Add your extensions here --> @@ -21,6 +22,8 @@ implementationClass="org.jastadd.tooling.RelAstGrammarSyntaxHighlighterFactory"/> <colorSettingsPage implementation="org.jastadd.tooling.RelAstGrammarColorSettingsPage"/> + + <annotator language="JAVA" implementationClass="org.jastadd.tooling.RelAstGrammarAnnotator"/> </extensions> <actions> -- GitLab