From 6aa2c918ea593365ec5fe259f157b1d2cb489c77 Mon Sep 17 00:00:00 2001 From: Johannes Mey <johannes.mey@tu-dresden.de> Date: Mon, 4 Jan 2021 01:01:48 +0100 Subject: [PATCH] add new annotator for T:T components and a quick fix --- .../tooling/RelAstGrammarAnnotator.java | 49 ++++++----------- .../tooling/RelAstGrammarJavaAnnotator.java | 54 +++++++++++++++++++ ...rammarRemoveRedundantComponentNameFix.java | 54 +++++++++++++++++++ ...lAstGrammarTypeReferenceImplExtension.java | 1 + src/main/resources/META-INF/plugin.xml | 4 +- 5 files changed, 127 insertions(+), 35 deletions(-) create mode 100644 src/main/java/org/jastadd/tooling/RelAstGrammarJavaAnnotator.java create mode 100644 src/main/java/org/jastadd/tooling/RelAstGrammarRemoveRedundantComponentNameFix.java diff --git a/src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java b/src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java index a103a37..ce19247 100644 --- a/src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java +++ b/src/main/java/org/jastadd/tooling/RelAstGrammarAnnotator.java @@ -6,50 +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.PsiClass; import com.intellij.psi.PsiElement; -import com.intellij.psi.javadoc.PsiDocComment; -import com.intellij.psi.javadoc.PsiDocTag; +import org.jastadd.tooling.psi.RelAstGrammarComponent; import org.jetbrains.annotations.NotNull; -import java.util.Arrays; -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); - - if (classOptional.isEmpty()) { - return; - } - - PsiDocComment docComment = classOptional.get().getDocComment(); - assert docComment != null; // asReferenceToTypeDecl ensures this is not null - - 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; + if (element instanceof RelAstGrammarComponent) { + RelAstGrammarComponent component = (RelAstGrammarComponent) element; + if (component.getTypeReference() != null && component.getDeclaredName() != null) { + String name = component.getDeclaredName().getText(); + if (name != null && !name.equals("") && name.equals(component.getTypeReference().getName())) { + holder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Redundant name") + .range(component.getDeclaredName().getTextRange()) + .highlightType(ProblemHighlightType.WEAK_WARNING) + .textAttributes(DefaultLanguageHighlighterColors.HIGHLIGHTED_REFERENCE) + .tooltip("When the name of a component is the same as its type, it can be omitted.") + .withFix(new RelAstGrammarRemoveRedundantComponentNameFix(component)) + .create(); + } + } } - 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(); } } diff --git a/src/main/java/org/jastadd/tooling/RelAstGrammarJavaAnnotator.java b/src/main/java/org/jastadd/tooling/RelAstGrammarJavaAnnotator.java new file mode 100644 index 0000000..5beaeff --- /dev/null +++ b/src/main/java/org/jastadd/tooling/RelAstGrammarJavaAnnotator.java @@ -0,0 +1,54 @@ +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.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.javadoc.PsiDocTag; +import org.jastadd.tooling.psi.RelAstGrammarComponent; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.jastadd.tooling.RelAstGrammarUtil.asReferenceToTypeDecl; + +public class RelAstGrammarJavaAnnotator implements Annotator { + + @Override + public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) { + + Optional<PsiClass> classOptional = asReferenceToTypeDecl(element); + + if (classOptional.isPresent()) { + PsiDocComment docComment = classOptional.get().getDocComment(); + assert docComment != null; // asReferenceToTypeDecl ensures this is not null + + 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(); + } + } + +} diff --git a/src/main/java/org/jastadd/tooling/RelAstGrammarRemoveRedundantComponentNameFix.java b/src/main/java/org/jastadd/tooling/RelAstGrammarRemoveRedundantComponentNameFix.java new file mode 100644 index 0000000..01a095d --- /dev/null +++ b/src/main/java/org/jastadd/tooling/RelAstGrammarRemoveRedundantComponentNameFix.java @@ -0,0 +1,54 @@ +package org.jastadd.tooling; + +import com.intellij.codeInsight.intention.impl.BaseIntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.util.IncorrectOperationException; +import org.jastadd.tooling.parser.RelAstGrammarTypes; +import org.jastadd.tooling.psi.RelAstGrammarComponent; +import org.jetbrains.annotations.NotNull; + +public class RelAstGrammarRemoveRedundantComponentNameFix extends BaseIntentionAction { + + private final RelAstGrammarComponent component; + + public RelAstGrammarRemoveRedundantComponentNameFix(RelAstGrammarComponent component) { + this.component = component; + } + + @NotNull + @Override + public String getText() { + return "Remove the name of component '" + component.getText() + "'"; + } + + @NotNull + @Override + public String getFamilyName() { + return "Edit component"; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return true; + } + + @Override + public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) throws + IncorrectOperationException { + PsiElement first = component.getDeclaredName(); + PsiElement last = component.getDeclaredName(); + while (last != null && last.getNode().getElementType() != RelAstGrammarTypes.COL) { + last = last.getNextSibling(); + } + if (last == null) { + throw new IncorrectOperationException("Unable to find ':' in component definition."); + } else { + component.deleteChildRange(first, last); + } + } + + +} diff --git a/src/main/java/org/jastadd/tooling/psi/impl/RelAstGrammarTypeReferenceImplExtension.java b/src/main/java/org/jastadd/tooling/psi/impl/RelAstGrammarTypeReferenceImplExtension.java index 74f719d..3b44b50 100644 --- a/src/main/java/org/jastadd/tooling/psi/impl/RelAstGrammarTypeReferenceImplExtension.java +++ b/src/main/java/org/jastadd/tooling/psi/impl/RelAstGrammarTypeReferenceImplExtension.java @@ -19,6 +19,7 @@ public class RelAstGrammarTypeReferenceImplExtension extends RelAstGrammarNamedE } public PsiElement setName(@NotNull String newName) { + // FIXME this can break the grammar when the type is used in an unnamed component (and in many other cases probably) ASTNode keyNode = getNode().getFirstChildNode(); if (keyNode != null) { RelAstGrammarTypeReference name = RelAstGrammarElementFactory.createTypeReference(getProject(), newName); diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index ce813c6..2263a9a 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -20,7 +20,9 @@ <colorSettingsPage implementation="org.jastadd.tooling.RelAstGrammarColorSettingsPage"/> - <annotator language="JAVA" implementationClass="org.jastadd.tooling.RelAstGrammarAnnotator"/> + <annotator language="JAVA" implementationClass="org.jastadd.tooling.RelAstGrammarJavaAnnotator"/> + + <annotator language="JastAddGrammar" implementationClass="org.jastadd.tooling.RelAstGrammarAnnotator"/> <codeInsight.lineMarkerProvider language="JAVA" implementationClass="org.jastadd.tooling.RelAstGrammarLineMarkerProvider"/> -- GitLab