feat: String escape sequence highlighting

This commit is contained in:
FalsePattern 2024-10-25 19:55:57 +02:00
parent 0d915f921e
commit 9d0f81bd8d
Signed by: falsepattern
GPG key ID: E930CDEC50C50E23
7 changed files with 150 additions and 45 deletions

View file

@ -17,6 +17,11 @@ Changelog structure reference:
## [Unreleased] ## [Unreleased]
### Added
- Zig
- Syntax highlighting for escape sequences in strings
### Fixed ### Fixed
- Zig - Zig

View file

@ -2,6 +2,7 @@ import de.undercouch.gradle.tasks.download.Download
import groovy.xml.XmlParser import groovy.xml.XmlParser
import org.jetbrains.changelog.Changelog import org.jetbrains.changelog.Changelog
import org.jetbrains.changelog.markdownToHTML import org.jetbrains.changelog.markdownToHTML
import org.jetbrains.grammarkit.tasks.GenerateLexerTask
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
import org.jetbrains.intellij.platform.gradle.tasks.PatchPluginXmlTask import org.jetbrains.intellij.platform.gradle.tasks.PatchPluginXmlTask
import org.jetbrains.intellij.platform.gradle.tasks.PublishPluginTask import org.jetbrains.intellij.platform.gradle.tasks.PublishPluginTask
@ -204,11 +205,21 @@ project(":zig") {
targetOutputDir = file("${grammarKitGenDir}/lexer/${rootPackagePath}/zig/lexer") targetOutputDir = file("${grammarKitGenDir}/lexer/${rootPackagePath}/zig/lexer")
} }
register<GenerateLexerTask>("generateStringLexer") {
sourceFile = file("src/main/grammar/ZigString.flex")
targetOutputDir = file("${grammarKitGenDir}/lexer/${rootPackagePath}/zig/stringlexer")
purgeOldFiles = true
}
generateParser { generateParser {
sourceFile = file("src/main/grammar/Zig.bnf") sourceFile = file("src/main/grammar/Zig.bnf")
pathToParser = "${rootPackagePath}/zig/psi/ZigParser.java" pathToParser = "${rootPackagePath}/zig/psi/ZigParser.java"
pathToPsiRoot = "${rootPackagePath}/zig/psi" pathToPsiRoot = "${rootPackagePath}/zig/psi"
} }
named("generateGrammars") {
dependsOn("generateStringLexer")
}
} }
} }

View file

@ -90,8 +90,8 @@ char_char= {mb_utf8_literal}
| {char_escape} | {char_escape}
| {ascii_char_not_nl_slash_squote} | {ascii_char_not_nl_slash_squote}
string_char= {char_escape} string_char= \\ .
| [^\\\"\n] | [^\"\n]
all_nl_wrap=[^\n]* [ \n]* all_nl_wrap=[^\n]* [ \n]*
all_nl_nowrap=[^\n]* \n all_nl_nowrap=[^\n]* \n

View file

@ -0,0 +1,60 @@
/*
* Copyright 2023-2024 FalsePattern
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.falsepattern.zigbrains.zig.stringlexer;
import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import static com.intellij.psi.TokenType.WHITE_SPACE;
import static com.intellij.psi.TokenType.BAD_CHARACTER;
import static com.falsepattern.zigbrains.zig.psi.ZigTypes.*;
import static com.intellij.psi.StringEscapesTokenTypes.*;
%%
%public
%class ZigStringLexer
%implements FlexLexer
%function advance
%type IElementType
hex=[0-9a-fA-F]
char_escape_unicode= "\\x" {hex} {hex} | "\\u{" {hex}+ "}"
char_escape_unicode_invalid= "\\x" | "\\u"
char_escape_single_valid= "\\" [nr\\t'\"]
char_escape_single_invalid= "\\" [^nr\\t'\"]
non_escape= [^\\\"\n]
%state STR
%%
<YYINITIAL> {
"\"" { yybegin(STR); return STRING_LITERAL_SINGLE; }
[^] { return STRING_LITERAL_SINGLE; }
}
<STR> {
{char_escape_unicode} { return VALID_STRING_ESCAPE_TOKEN; }
{char_escape_unicode_invalid} { return INVALID_UNICODE_ESCAPE_TOKEN; }
{char_escape_single_valid} { return VALID_STRING_ESCAPE_TOKEN; }
{char_escape_single_invalid} { return INVALID_CHARACTER_ESCAPE_TOKEN; }
[^] { return STRING_LITERAL_SINGLE; }
}

View file

@ -63,6 +63,9 @@ public class ZigColorSettingsPage implements ColorSettingsPage {
new AttributesDescriptor("Property//Declaration", ZigSyntaxHighlighter.PROPERTY_DECL), new AttributesDescriptor("Property//Declaration", ZigSyntaxHighlighter.PROPERTY_DECL),
new AttributesDescriptor("Property//Reference", ZigSyntaxHighlighter.PROPERTY_REF), new AttributesDescriptor("Property//Reference", ZigSyntaxHighlighter.PROPERTY_REF),
new AttributesDescriptor("String", ZigSyntaxHighlighter.STRING), new AttributesDescriptor("String", ZigSyntaxHighlighter.STRING),
new AttributesDescriptor("String//Escape", ZigSyntaxHighlighter.STRING_ESC_V),
new AttributesDescriptor("String//Escape//Invalid char", ZigSyntaxHighlighter.STRING_ESC_I_C),
new AttributesDescriptor("String//Escape//Invalid unicode", ZigSyntaxHighlighter.STRING_ESC_I_U),
new AttributesDescriptor("Struct//Declaration", ZigSyntaxHighlighter.STRUCT_DECL), new AttributesDescriptor("Struct//Declaration", ZigSyntaxHighlighter.STRUCT_DECL),
new AttributesDescriptor("Struct//Reference", ZigSyntaxHighlighter.STRUCT_REF), new AttributesDescriptor("Struct//Reference", ZigSyntaxHighlighter.STRUCT_REF),
new AttributesDescriptor("Type//Declaration", ZigSyntaxHighlighter.TYPE_DECL), new AttributesDescriptor("Type//Declaration", ZigSyntaxHighlighter.TYPE_DECL),

View file

@ -16,6 +16,7 @@
package com.falsepattern.zigbrains.zig.highlighter; package com.falsepattern.zigbrains.zig.highlighter;
import com.falsepattern.zigbrains.zig.lexer.ZigHighlightingLexer;
import com.falsepattern.zigbrains.zig.lexer.ZigLexerAdapter; import com.falsepattern.zigbrains.zig.lexer.ZigLexerAdapter;
import com.falsepattern.zigbrains.zig.psi.ZigTypes; import com.falsepattern.zigbrains.zig.psi.ZigTypes;
import com.intellij.lexer.Lexer; import com.intellij.lexer.Lexer;
@ -23,6 +24,7 @@ import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
import com.intellij.openapi.editor.HighlighterColors; import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase; import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
import com.intellij.psi.StringEscapesTokenTypes;
import com.intellij.psi.TokenType; import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
import com.redhat.devtools.lsp4ij.features.semanticTokens.SemanticTokensHighlightingColors; import com.redhat.devtools.lsp4ij.features.semanticTokens.SemanticTokensHighlightingColors;
@ -35,48 +37,51 @@ import java.util.Map;
public class ZigSyntaxHighlighter extends SyntaxHighlighterBase { public class ZigSyntaxHighlighter extends SyntaxHighlighterBase {
// @formatter:off // @formatter:off
public static final TextAttributesKey public static final TextAttributesKey
BAD_CHAR = createKey("BAD_CHARACTER" , HighlighterColors.BAD_CHARACTER ), BAD_CHAR = createKey("BAD_CHARACTER" , HighlighterColors.BAD_CHARACTER ),
BUILTIN = createKey("BUILTIN" , SemanticTokensHighlightingColors.STATIC_METHOD ), BUILTIN = createKey("BUILTIN" , SemanticTokensHighlightingColors.STATIC_METHOD ),
CHAR = createKey("CHAR" , SemanticTokensHighlightingColors.NUMBER ), CHAR = createKey("CHAR" , SemanticTokensHighlightingColors.NUMBER ),
COMMENT = createKey("COMMENT" , SemanticTokensHighlightingColors.COMMENT ), COMMENT = createKey("COMMENT" , SemanticTokensHighlightingColors.COMMENT ),
COMMENT_DOC = createKey("COMMENT_DOC" , DefaultLanguageHighlighterColors.DOC_COMMENT ), COMMENT_DOC = createKey("COMMENT_DOC" , DefaultLanguageHighlighterColors.DOC_COMMENT ),
ENUM_DECL = createKey("ENUM_DECL" , SemanticTokensHighlightingColors.CLASS_DECLARATION ), ENUM_DECL = createKey("ENUM_DECL" , SemanticTokensHighlightingColors.CLASS_DECLARATION ),
ENUM_REF = createKey("ENUM" , SemanticTokensHighlightingColors.CLASS ), ENUM_REF = createKey("ENUM" , SemanticTokensHighlightingColors.CLASS ),
ENUM_MEMBER_DECL = createKey("ENUM_MEMBER_DECL" , SemanticTokensHighlightingColors.STATIC_PROPERTY ), ENUM_MEMBER_DECL = createKey("ENUM_MEMBER_DECL" , SemanticTokensHighlightingColors.STATIC_PROPERTY ),
ENUM_MEMBER_REF = createKey("ENUM_MEMBER" , ENUM_MEMBER_DECL ), ENUM_MEMBER_REF = createKey("ENUM_MEMBER" , ENUM_MEMBER_DECL ),
ERROR_TAG_DECL = createKey("ERROR_TAG_DECL" , SemanticTokensHighlightingColors.STATIC_PROPERTY ), ERROR_TAG_DECL = createKey("ERROR_TAG_DECL" , SemanticTokensHighlightingColors.STATIC_PROPERTY ),
ERROR_TAG_REF = createKey("ERROR_TAG" , ERROR_TAG_DECL ), ERROR_TAG_REF = createKey("ERROR_TAG" , ERROR_TAG_DECL ),
PROPERTY_DECL = createKey("PROPERTY_DECL" , SemanticTokensHighlightingColors.PROPERTY ), PROPERTY_DECL = createKey("PROPERTY_DECL" , SemanticTokensHighlightingColors.PROPERTY ),
PROPERTY_REF = createKey("PROPERTY" , PROPERTY_DECL ), PROPERTY_REF = createKey("PROPERTY" , PROPERTY_DECL ),
FUNCTION_DECL = createKey("FUNCTION_DECL" , SemanticTokensHighlightingColors.FUNCTION_DECLARATION), FUNCTION_DECL = createKey("FUNCTION_DECL" , SemanticTokensHighlightingColors.FUNCTION_DECLARATION ),
FUNCTION_DECL_GEN = createKey("FUNCTION_DECL_GEN" , FUNCTION_DECL ), FUNCTION_DECL_GEN = createKey("FUNCTION_DECL_GEN" , FUNCTION_DECL ),
FUNCTION_REF = createKey("FUNCTION" , SemanticTokensHighlightingColors.FUNCTION ), FUNCTION_REF = createKey("FUNCTION" , SemanticTokensHighlightingColors.FUNCTION ),
FUNCTION_REF_GEN = createKey("FUNCTION_GEN" , FUNCTION_REF ), FUNCTION_REF_GEN = createKey("FUNCTION_GEN" , FUNCTION_REF ),
KEYWORD = createKey("KEYWORD" , SemanticTokensHighlightingColors.KEYWORD ), KEYWORD = createKey("KEYWORD" , SemanticTokensHighlightingColors.KEYWORD ),
LABEL_DECL = createKey("LABEL_DECL" , SemanticTokensHighlightingColors.LABEL ), LABEL_DECL = createKey("LABEL_DECL" , SemanticTokensHighlightingColors.LABEL ),
LABEL_REF = createKey("LABEL" , LABEL_DECL ), LABEL_REF = createKey("LABEL" , LABEL_DECL ),
METHOD_DECL = createKey("METHOD_DECL" , FUNCTION_DECL ), METHOD_DECL = createKey("METHOD_DECL" , FUNCTION_DECL ),
METHOD_DECL_GEN = createKey("METHOD_DECL_GEN" , METHOD_DECL ), METHOD_DECL_GEN = createKey("METHOD_DECL_GEN" , METHOD_DECL ),
METHOD_REF = createKey("METHOD" , FUNCTION_REF ), METHOD_REF = createKey("METHOD" , FUNCTION_REF ),
METHOD_REF_GEN = createKey("METHOD_GEN" , METHOD_REF ), METHOD_REF_GEN = createKey("METHOD_GEN" , METHOD_REF ),
NAMESPACE_DECL = createKey("NAMESPACE_DECL" , SemanticTokensHighlightingColors.CLASS_DECLARATION ), NAMESPACE_DECL = createKey("NAMESPACE_DECL" , SemanticTokensHighlightingColors.CLASS_DECLARATION ),
NAMESPACE_REF = createKey("NAMESPACE" , SemanticTokensHighlightingColors.CLASS ), NAMESPACE_REF = createKey("NAMESPACE" , SemanticTokensHighlightingColors.CLASS ),
NUMBER = createKey("NUMBER" , SemanticTokensHighlightingColors.NUMBER ), NUMBER = createKey("NUMBER" , SemanticTokensHighlightingColors.NUMBER ),
OPERATOR = createKey("OPERATOR" , SemanticTokensHighlightingColors.OPERATOR ), OPERATOR = createKey("OPERATOR" , SemanticTokensHighlightingColors.OPERATOR ),
PARAMETER = createKey("PARAMETER" , SemanticTokensHighlightingColors.PARAMETER ), PARAMETER = createKey("PARAMETER" , SemanticTokensHighlightingColors.PARAMETER ),
STRING = createKey("STRING" , SemanticTokensHighlightingColors.STRING ), STRING = createKey("STRING" , SemanticTokensHighlightingColors.STRING ),
STRUCT_DECL = createKey("STRUCT_DECL" , SemanticTokensHighlightingColors.CLASS_DECLARATION ), STRING_ESC_V = createKey("STRING_ESC_V" , DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE ),
STRUCT_REF = createKey("STRUCT" , SemanticTokensHighlightingColors.CLASS ), STRING_ESC_I_C = createKey("STRING_ESC_I_C" , DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE ),
TYPE_DECL = createKey("TYPE_DECL" , SemanticTokensHighlightingColors.CLASS_DECLARATION ), STRING_ESC_I_U = createKey("STRING_ESC_I_U" , DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE ),
TYPE_DECL_GEN = createKey("TYPE_DECL_GEN" , TYPE_DECL ), STRUCT_DECL = createKey("STRUCT_DECL" , SemanticTokensHighlightingColors.CLASS_DECLARATION ),
TYPE_REF = createKey("TYPE" , SemanticTokensHighlightingColors.TYPE ), STRUCT_REF = createKey("STRUCT" , SemanticTokensHighlightingColors.CLASS ),
TYPE_REF_GEN = createKey("TYPE_GEN" , TYPE_REF ), TYPE_DECL = createKey("TYPE_DECL" , SemanticTokensHighlightingColors.CLASS_DECLARATION ),
TYPE_PARAM = createKey("TYPE_PARAM" , SemanticTokensHighlightingColors.TYPE_PARAMETER ), TYPE_DECL_GEN = createKey("TYPE_DECL_GEN" , TYPE_DECL ),
TYPE_PARAM_DECL = createKey("TYPE_PARAM_DECL" , TYPE_PARAM ), TYPE_REF = createKey("TYPE" , SemanticTokensHighlightingColors.TYPE ),
VARIABLE_DECL = createKey("VARIABLE_DECL" , DefaultLanguageHighlighterColors.LOCAL_VARIABLE ), TYPE_REF_GEN = createKey("TYPE_GEN" , TYPE_REF ),
VARIABLE_DECL_DEPR= createKey("VARIABLE_DECL_DEPR" , VARIABLE_DECL ), TYPE_PARAM = createKey("TYPE_PARAM" , SemanticTokensHighlightingColors.TYPE_PARAMETER ),
VARIABLE_REF = createKey("VARIABLE" , VARIABLE_DECL ), TYPE_PARAM_DECL = createKey("TYPE_PARAM_DECL" , TYPE_PARAM ),
VARIABLE_REF_DEPR = createKey("VARIABLE_REF_DEPL" , VARIABLE_REF ); VARIABLE_DECL = createKey("VARIABLE_DECL" , DefaultLanguageHighlighterColors.LOCAL_VARIABLE ),
VARIABLE_DECL_DEPR= createKey("VARIABLE_DECL_DEPR" , VARIABLE_DECL ),
VARIABLE_REF = createKey("VARIABLE" , VARIABLE_DECL ),
VARIABLE_REF_DEPR = createKey("VARIABLE_REF_DEPL" , VARIABLE_REF );
// @formatter:on // @formatter:on
private static final TextAttributesKey[] EMPTY_KEYS = new TextAttributesKey[0]; private static final TextAttributesKey[] EMPTY_KEYS = new TextAttributesKey[0];
private static final Map<IElementType, TextAttributesKey[]> KEYMAP = new HashMap<>(); private static final Map<IElementType, TextAttributesKey[]> KEYMAP = new HashMap<>();
@ -102,6 +107,9 @@ public class ZigSyntaxHighlighter extends SyntaxHighlighterBase {
} }
addMapping(BUILTIN, ZigTypes.BUILTINIDENTIFIER); addMapping(BUILTIN, ZigTypes.BUILTINIDENTIFIER);
addMapping(STRING, ZigTypes.STRING_LITERAL_SINGLE, ZigTypes.STRING_LITERAL_MULTI); addMapping(STRING, ZigTypes.STRING_LITERAL_SINGLE, ZigTypes.STRING_LITERAL_MULTI);
addMapping(STRING_ESC_V, StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN);
addMapping(STRING_ESC_I_C, StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN);
addMapping(STRING_ESC_I_U, StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN);
addMapping(BAD_CHAR, TokenType.BAD_CHARACTER); addMapping(BAD_CHAR, TokenType.BAD_CHARACTER);
addMapping(NUMBER, ZigTypes.INTEGER, ZigTypes.FLOAT); addMapping(NUMBER, ZigTypes.INTEGER, ZigTypes.FLOAT);
addMapping(CHAR, ZigTypes.CHAR_LITERAL); addMapping(CHAR, ZigTypes.CHAR_LITERAL);
@ -120,7 +128,7 @@ public class ZigSyntaxHighlighter extends SyntaxHighlighterBase {
@Override @Override
public @NotNull Lexer getHighlightingLexer() { public @NotNull Lexer getHighlightingLexer() {
return new ZigLexerAdapter(); return new ZigHighlightingLexer();
} }
@Override @Override

View file

@ -0,0 +1,18 @@
package com.falsepattern.zigbrains.zig.lexer;
import com.falsepattern.zigbrains.zig.psi.ZigTypes;
import com.intellij.lexer.FlexAdapter;
import com.intellij.lexer.LayeredLexer;
import com.intellij.lexer.MergingLexerAdapter;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import lombok.val;
public class ZigHighlightingLexer extends LayeredLexer {
public ZigHighlightingLexer() {
super(new ZigLexerAdapter());
val stringLexer = new MergingLexerAdapter(new FlexAdapter(new com.falsepattern.zigbrains.zig.stringlexer.ZigStringLexer(null)), TokenSet.create(
ZigTypes.STRING_LITERAL_SINGLE));
registerSelfStoppingLayer(stringLexer, new IElementType[]{ZigTypes.STRING_LITERAL_SINGLE}, IElementType.EMPTY_ARRAY);
}
}