Skip to content

Commit c26fddd

Browse files
authored
Implicit token highlighting (#383)
* Introduce a TextAttributesKey for implicit markers * Adapt BnfColorSettingsPage to showcase implicit tokens highlighting. Replace some value-matched explicit tokens with their names to better show the difference between implicit and explicit name-matched tokens * Adapt BnfAnnotator to detect implicit tokens and highlight them accordingly * fix: Add @language("HTML") annotation to BnfColorSettingsPage::getDemoText's return type so IDEA highlights the string literal * fix: Use instanceof with binding variable throughout BnfAnnotator * fix: Rename TextAttributesKey TOKEN to EXPLICIT_TOKEN
1 parent 67aca76 commit c26fddd

File tree

3 files changed

+41
-29
lines changed

3 files changed

+41
-29
lines changed

src/org/intellij/grammar/editor/BnfAnnotator.java

+29-21
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ final class BnfAnnotator implements Annotator, DumbAware {
3232
@Override
3333
public void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder annotationHolder) {
3434
PsiElement parent = psiElement.getParent();
35-
if (parent instanceof BnfRule && ((BnfRule)parent).getId() == psiElement) {
36-
addRuleHighlighting((BnfRule)parent, psiElement, annotationHolder);
35+
if (parent instanceof BnfRule rule && rule.getId() == psiElement) {
36+
addRuleHighlighting(rule, psiElement, annotationHolder);
3737
}
38-
else if (parent instanceof BnfAttr && ((BnfAttr)parent).getId() == psiElement) {
38+
else if (parent instanceof BnfAttr attr && attr.getId() == psiElement) {
3939
annotationHolder.newSilentAnnotation(HighlightSeverity.INFORMATION)
4040
.range(psiElement)
4141
.textAttributes(BnfSyntaxHighlighter.ATTRIBUTE)
@@ -47,9 +47,9 @@ else if (parent instanceof BnfModifier) {
4747
.textAttributes(BnfSyntaxHighlighter.KEYWORD)
4848
.create();
4949
}
50-
else if (parent instanceof BnfListEntry && ((BnfListEntry)parent).getId() == psiElement) {
51-
boolean hasValue = ((BnfListEntry)parent).getLiteralExpression() != null;
52-
BnfAttr attr = PsiTreeUtil.getParentOfType(parent, BnfAttr.class);
50+
else if (parent instanceof BnfListEntry listEntry && listEntry.getId() == psiElement) {
51+
boolean hasValue = listEntry.getLiteralExpression() != null;
52+
BnfAttr attr = PsiTreeUtil.getParentOfType(listEntry, BnfAttr.class);
5353
KnownAttribute<?> attribute = attr != null ? KnownAttribute.getCompatibleAttribute(attr.getName()) : null;
5454
if (attribute == KnownAttribute.METHODS && !hasValue) {
5555
annotationHolder.newSilentAnnotation(HighlightSeverity.INFORMATION)
@@ -58,48 +58,56 @@ else if (parent instanceof BnfListEntry && ((BnfListEntry)parent).getId() == psi
5858
.create();
5959
}
6060
}
61-
else if (psiElement instanceof BnfReferenceOrToken) {
61+
else if (psiElement instanceof BnfReferenceOrToken refOrToken) {
6262
if (parent instanceof BnfAttr) {
63-
String text = psiElement.getText();
63+
String text = refOrToken.getText();
6464
if ("true".equals(text) || "false".equals(text)) {
6565
annotationHolder.newSilentAnnotation(HighlightSeverity.INFORMATION)
66-
.range(psiElement)
66+
.range(refOrToken)
6767
.textAttributes(BnfSyntaxHighlighter.KEYWORD)
6868
.create();
6969
return;
7070
}
7171
}
72-
PsiReference reference = psiElement.getReference();
72+
PsiReference reference = refOrToken.getReference();
7373
Object resolve = reference == null ? null : reference.resolve();
74-
if (resolve instanceof BnfRule) {
75-
addRuleHighlighting((BnfRule)resolve, psiElement, annotationHolder);
74+
if (resolve instanceof BnfRule rule) {
75+
addRuleHighlighting(rule, refOrToken, annotationHolder);
7676
}
7777
else if (resolve instanceof BnfAttr) {
7878
annotationHolder.newSilentAnnotation(HighlightSeverity.INFORMATION)
79-
.range(psiElement)
79+
.range(refOrToken)
8080
.textAttributes(BnfSyntaxHighlighter.ATTRIBUTE)
8181
.create();
8282
}
83-
else if (GrammarUtil.isExternalReference(psiElement)) {
84-
if (resolve == null && parent instanceof BnfExternalExpression && ((BnfExternalExpression)parent).getArguments().isEmpty() &&
85-
ParserGeneratorUtil.Rule.isMeta(ParserGeneratorUtil.Rule.of((BnfReferenceOrToken)psiElement))) {
83+
else if (GrammarUtil.isExternalReference(refOrToken)) {
84+
if (resolve == null && parent instanceof BnfExternalExpression extExpr && extExpr.getArguments().isEmpty() &&
85+
ParserGeneratorUtil.Rule.isMeta(ParserGeneratorUtil.Rule.of(refOrToken))) {
8686
annotationHolder.newSilentAnnotation(HighlightSeverity.INFORMATION)
8787
.range(parent)
8888
.textAttributes(BnfSyntaxHighlighter.META_PARAM)
8989
.create();
9090
}
9191
else {
9292
annotationHolder.newSilentAnnotation(HighlightSeverity.INFORMATION)
93-
.range(psiElement)
93+
.range(refOrToken)
9494
.textAttributes(BnfSyntaxHighlighter.EXTERNAL)
9595
.create();
9696
}
9797
}
9898
else if (resolve == null) {
99-
annotationHolder.newSilentAnnotation(HighlightSeverity.INFORMATION)
100-
.range(psiElement)
101-
.textAttributes(BnfSyntaxHighlighter.TOKEN)
102-
.create();
99+
var text = refOrToken.getId().getText();
100+
if (RuleGraphHelper.getTokenNameToTextMap((BnfFile)refOrToken.getContainingFile()).containsKey(text)) {
101+
annotationHolder.newSilentAnnotation(HighlightSeverity.INFORMATION)
102+
.range(refOrToken)
103+
.textAttributes(BnfSyntaxHighlighter.EXPLICIT_TOKEN)
104+
.create();
105+
} else {
106+
annotationHolder.newSilentAnnotation(HighlightSeverity.INFORMATION)
107+
.range(refOrToken)
108+
.textAttributes(BnfSyntaxHighlighter.IMPLICIT_TOKEN)
109+
.create();
110+
}
103111
}
104112
}
105113
else if (psiElement instanceof BnfStringLiteralExpression) {

src/org/intellij/grammar/editor/BnfColorSettingsPage.java

+10-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.intellij.openapi.options.colors.ColorSettingsPage;
1212
import org.intellij.grammar.BnfIcons;
1313
import org.intellij.grammar.GrammarKitBundle;
14+
import org.intellij.lang.annotations.Language;
1415
import org.jetbrains.annotations.NonNls;
1516
import org.jetbrains.annotations.NotNull;
1617

@@ -33,7 +34,8 @@ final class BnfColorSettingsPage implements ColorSettingsPage {
3334
new AttributesDescriptor("String", STRING),
3435
new AttributesDescriptor("Number", NUMBER),
3536
new AttributesDescriptor("Keyword", KEYWORD),
36-
new AttributesDescriptor("Token", TOKEN),
37+
new AttributesDescriptor("Explicit token", EXPLICIT_TOKEN),
38+
new AttributesDescriptor("Implicit token", IMPLICIT_TOKEN),
3739
new AttributesDescriptor("Rule", RULE),
3840
new AttributesDescriptor("Attribute", ATTRIBUTE),
3941
new AttributesDescriptor("Meta rule", META_RULE),
@@ -76,7 +78,7 @@ public Icon getIcon() {
7678
}
7779

7880
@Override
79-
public @NotNull String getDemoText() {
81+
public @NotNull @Language("HTML") String getDemoText() {
8082
return """
8183
/*
8284
* Sample grammar
@@ -94,11 +96,11 @@ public Icon getIcon() {
9496
}
9597
// Grammar rules
9698
<r>root</r> ::= <r>header</r> <r>content</r>
97-
<r>header</r> ::= <t>DECLARE</t> <r>reference</r>
99+
<r>header</r> ::= <it>DECLARE</it> <r>reference</r>
98100
<k>external</k> <r>reference</r> ::= <e>parseReference</e>
99-
<k>private</k> <k>meta</k> <mr>comma_list</mr> ::= <pin><s>'('</s></pin> <mp><<p>></mp> (<pin><s>','</s></pin> <mp><<p>></mp>) * ')'
100-
<k>private</k> <r>content</r> ::= <pin><t>AS</t></pin> <<<mr>comma_list</mr> <ru><r>element</r></ru>>> {<a>pin</a>=1}
101-
<ru><r>element</r></ru> ::= <r>reference</r> [ {<pa>'+'</pa> | <pa>'-'</pa>} <r>reference</r> <t>ONLY</t>?] {<a>recoverWhile</a>=<r>element_recover</r>}
101+
<k>private</k> <k>meta</k> <mr>comma_list</mr> ::= <pin><t>LEFT_PAREN</t></pin> <mp><<p>></mp> (<pin><s>','</s></pin> <mp><<p>></mp>) * <t>RIGHT_PAREN</t>
102+
<k>private</k> <r>content</r> ::= <pin><it>AS</it></pin> <<<mr>comma_list</mr> <ru><r>element</r></ru>>> {<a>pin</a>=1}
103+
<ru><r>element</r></ru> ::= <r>reference</r> [ {<pa>'+'</pa> | <pa>'-'</pa>} <r>reference</r> <it>ONLY</it>?] {<a>recoverWhile</a>=<r>element_recover</r>}
102104
<k>private</k> <r>element_recover</r> ::= !(',' | ')')
103105
104106
""";
@@ -112,7 +114,8 @@ public Map<String, TextAttributesKey> getAdditionalHighlightingTagToDescriptorMa
112114
map.put("mr", META_RULE);
113115
map.put("a", ATTRIBUTE);
114116
map.put("pa", PATTERN);
115-
map.put("t", TOKEN);
117+
map.put("t", EXPLICIT_TOKEN);
118+
map.put("it", IMPLICIT_TOKEN);
116119
map.put("k", KEYWORD);
117120
map.put("e", EXTERNAL);
118121
map.put("pin", PIN_MARKER);

src/org/intellij/grammar/editor/BnfSyntaxHighlighter.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ class BnfSyntaxHighlighter extends SyntaxHighlighterBase {
2727
public static final TextAttributesKey PATTERN = createTextAttributesKey("BNF_PATTERN", DefaultLanguageHighlighterColors.INSTANCE_FIELD);
2828
public static final TextAttributesKey NUMBER = createTextAttributesKey("BNF_NUMBER", DefaultLanguageHighlighterColors.NUMBER);
2929
public static final TextAttributesKey KEYWORD = createTextAttributesKey("BNF_KEYWORD", DefaultLanguageHighlighterColors.MARKUP_ATTRIBUTE);
30-
public static final TextAttributesKey TOKEN = createTextAttributesKey("BNF_TOKEN", DefaultLanguageHighlighterColors.STRING);
30+
public static final TextAttributesKey EXPLICIT_TOKEN = createTextAttributesKey("BNF_TOKEN", DefaultLanguageHighlighterColors.STRING);
31+
public static final TextAttributesKey IMPLICIT_TOKEN = createTextAttributesKey("BNF_IMPLICIT_TOKEN", DefaultLanguageHighlighterColors.STATIC_FIELD);
3132
public static final TextAttributesKey RULE = createTextAttributesKey("BNF_RULE", DefaultLanguageHighlighterColors.KEYWORD);
3233
public static final TextAttributesKey META_RULE = createTextAttributesKey("BNF_META_RULE", DefaultLanguageHighlighterColors.KEYWORD);
3334
public static final TextAttributesKey META_PARAM = createTextAttributesKey("BNF_META_RULE_PARAM");

0 commit comments

Comments
 (0)