From ae08287d7edce4d125e733166322c0850a5d7759 Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Tue, 11 Mar 2025 02:01:56 +0100 Subject: [PATCH] backport: 21.1.0 --- CHANGELOG.md | 12 ++ core/src/main/grammar/Zig.flex | 1 + core/src/main/grammar/Zon.bnf | 63 ++++---- core/src/main/grammar/Zon.flex | 130 ++++++++++++---- .../zigbrains/zon/comments/ZonCommenter.kt | 2 +- .../completion/ZonCompletionContributor.kt | 146 ------------------ .../zon/folding/ZonFoldingBuilder.kt | 58 ------- .../zigbrains/zon/formatter/ZonBlock.kt | 63 +++++--- .../zon/highlighting/ZonColorSettingsPage.kt | 80 ---------- .../zon/highlighting/ZonSyntaxHighlighter.kt | 58 ++++--- .../ZonHighlightingLexer.kt} | 26 +++- .../zigbrains/zon/pairing/ZonBraceMatcher.kt | 6 +- .../zigbrains/zon/pairing/ZonQuoteHandler.kt | 9 +- .../zigbrains/zon/parser/ZonTokenSets.kt | 4 +- .../psi/impl/mixins/ZonIdentifierMixinImpl.kt | 37 ----- .../zigbrains/zon/psi/mixins/ZonEntryMixin.kt | 29 ---- .../zon/psi/mixins/ZonIdentifierMixin.kt | 30 ---- .../resources/META-INF/zigbrains-core.xml | 8 - gradle.properties | 2 +- .../main/resources/META-INF/zigbrains-lsp.xml | 5 + 20 files changed, 256 insertions(+), 513 deletions(-) delete mode 100644 core/src/main/kotlin/com/falsepattern/zigbrains/zon/completion/ZonCompletionContributor.kt delete mode 100644 core/src/main/kotlin/com/falsepattern/zigbrains/zon/folding/ZonFoldingBuilder.kt delete mode 100644 core/src/main/kotlin/com/falsepattern/zigbrains/zon/highlighting/ZonColorSettingsPage.kt rename core/src/main/kotlin/com/falsepattern/zigbrains/zon/{psi/impl/mixins/ZonEntryMixinImpl.kt => lexer/ZonHighlightingLexer.kt} (52%) delete mode 100644 core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/impl/mixins/ZonIdentifierMixinImpl.kt delete mode 100644 core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/mixins/ZonEntryMixin.kt delete mode 100644 core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/mixins/ZonIdentifierMixin.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index e96833c9..76b0f6f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,18 @@ Changelog structure reference: ## [Unreleased] +## [21.1.0] + +### Added + +- Zon + - ZLS integration + +### Changed + +- Zon + - Fully refactored the parser for parity with the zig parser + ## [21.0.0] ### Added diff --git a/core/src/main/grammar/Zig.flex b/core/src/main/grammar/Zig.flex index 1a36a5ab..11281fb5 100644 --- a/core/src/main/grammar/Zig.flex +++ b/core/src/main/grammar/Zig.flex @@ -34,6 +34,7 @@ import static com.falsepattern.zigbrains.zig.psi.ZigTypes.*; %implements FlexLexer %function advance %type IElementType +%unicode CRLF=\R WHITE_SPACE=[\s]+ diff --git a/core/src/main/grammar/Zon.bnf b/core/src/main/grammar/Zon.bnf index 2bd91e0e..de27b71e 100644 --- a/core/src/main/grammar/Zon.bnf +++ b/core/src/main/grammar/Zon.bnf @@ -34,46 +34,57 @@ elementTypeClass="com.falsepattern.zigbrains.zon.parser.ZonElementType" tokenTypeClass="com.falsepattern.zigbrains.zon.parser.ZonTokenType" tokens=[ + LINE_COMMENT='comment' DOT='.' + EQUAL='=' LBRACE='{' RBRACE='}' - EQ='=' COMMA=',' - COMMENT='comment' - ID='identifier' - STRING_LITERAL_SINGLE='string' - LINE_STRING='multiline string' - BAD_STRING='unterminated string' - BOOL_TRUE='true' - BOOL_FALSE='false' + KEYWORD_FALSE='false' + KEYWORD_TRUE='true' + KEYWORD_NULL='null' + NUM_NAN='nan' + NUM_INF='inf' + CHAR_LITERAL='char literal' + STRING_LITERAL_SINGLE='string literal' + STRING_LITERAL_MULTI='multiline string literal' + FLOAT='float' + INTEGER='integer' + IDENTIFIER='identifier' + BAD_SQUOT='unterminated quote' + BAD_DQUOT='unterminated double quote' ] - - //Mixins - mixin("entry")="com.falsepattern.zigbrains.zon.psi.impl.mixins.ZonEntryMixinImpl" - implements("entry")="com.falsepattern.zigbrains.zon.psi.mixins.ZonEntryMixin" - - mixin("identifier")="com.falsepattern.zigbrains.zon.psi.impl.mixins.ZonIdentifierMixinImpl" - implements("identifier")="com.falsepattern.zigbrains.zon.psi.mixins.ZonIdentifierMixin" } -zonFile ::= entry +Root ::= Expr -entry ::= DOT LBRACE (list | struct | ()) RBRACE +Expr +::= CHAR_LITERAL + | StringLiteral + | DOT IDENTIFIER + | DOT InitList + | Bool + | Number + | KEYWORD_NULL -struct ::= (property | property_placeholder) (COMMA (property_placeholder? property property_placeholder? | property_placeholder))* COMMA? -list ::= value (COMMA value)* COMMA? +InitList +::= LBRACE ZB_InitList_Body RBRACE {pin=1} -property ::= DOT identifier EQ value +private ZB_InitList_Body +::= FieldInit (COMMA ZB_InitList_FieldInit)* COMMA? + | Expr (COMMA ZB_InitList_Expr)* COMMA? + | () -identifier ::= ID +private ZB_InitList_FieldInit ::= FieldInit {recoverWhile="ZB_InitList_Recover"} +private ZB_InitList_Expr ::= Expr {recoverWhile="ZB_InitList_Recover"} -property_placeholder ::= DOT? INTELLIJ_COMPLETION_DUMMY +private ZB_InitList_Recover ::= !(COMMA | RBRACE) -private value ::= entry | boolean | STRING_LITERAL | value_placeholder +FieldInit ::= DOT IDENTIFIER EQUAL Expr -value_placeholder ::= INTELLIJ_COMPLETION_DUMMY +Bool ::= KEYWORD_TRUE | KEYWORD_FALSE -boolean ::= BOOL_TRUE | BOOL_FALSE +Number ::= FLOAT | INTEGER | NUM_NAN | NUM_INF -STRING_LITERAL ::= STRING_LITERAL_SINGLE | LINE_STRING+ +StringLiteral ::= STRING_LITERAL_SINGLE | STRING_LITERAL_MULTI \ No newline at end of file diff --git a/core/src/main/grammar/Zon.flex b/core/src/main/grammar/Zon.flex index 0937e36d..ccc0a4fb 100644 --- a/core/src/main/grammar/Zon.flex +++ b/core/src/main/grammar/Zon.flex @@ -38,52 +38,120 @@ import static com.falsepattern.zigbrains.zon.psi.ZonTypes.*; CRLF=\R WHITE_SPACE=[\s]+ -LINE_COMMENT="//" [^\n]* | "////" [^\n]* -COMMENT="///".* - -ID=[A-Za-z_][A-Za-z0-9_]* +bin=[01] +bin_="_"? {bin} +oct=[0-7] +oct_="_"? {oct} hex=[0-9a-fA-F] -char_escape - = "\\x" {hex} {hex} - | "\\u{" {hex}+ "}" - | "\\" [nr\\t'\"] +hex_="_"? {hex} +dec=[0-9] +dec_="_"? {dec} -string_char - = {char_escape} - | [^\\\"\n] +bin_int={bin} {bin_}* +oct_int={oct} {oct_}* +dec_int={dec} {dec_}* +hex_int={hex} {hex_}* -LINE_STRING=("\\\\" [^\n]* [ \n]*)+ +char_char= \\ . + | [^\'\n] -%state STRING_LITERAL -%state ID_STRING -%state UNCLOSED_STRING +string_char= \\ . + | [^\"\n] + +all_nl_wrap=[^\n]* [ \n]* +all_no_nl=[^\n]+ + + +FLOAT= "0x" {hex_int} "." {hex_int} ([pP] [-+]? {dec_int})? + | {dec_int} "." {dec_int} ([eE] [-+]? {dec_int})? + | "0x" {hex_int} [pP] [-+]? {dec_int} + | {dec_int} [eE] [-+]? {dec_int} + +INTEGER= "0b" {bin_int} + | "0o" {oct_int} + | "0x" {hex_int} + | {dec_int} + +IDENTIFIER_PLAIN=[A-Za-z_][A-Za-z0-9_]* + +%state STR_LIT +%state STR_MULT_LINE +%state CHAR_LIT + +%state ID_QUOT +%state UNT_SQUOT +%state UNT_DQUOT + +%state LINE_CMT %% +//Comments + + "//" { yybegin(LINE_CMT); } + {all_nl_wrap} "//" { } + {all_no_nl} { } + \n { yybegin(YYINITIAL); return LINE_COMMENT; } + <> { yybegin(YYINITIAL); return LINE_COMMENT; } + +//Symbols - {WHITE_SPACE} { return WHITE_SPACE; } "." { return DOT; } - "IntellijIdeaRulezzz" { return INTELLIJ_COMPLETION_DUMMY; } + "=" { return EQUAL; } "{" { return LBRACE; } "}" { return RBRACE; } - "=" { return EQ; } "," { return COMMA; } - "true" { return BOOL_TRUE; } - "false" { return BOOL_FALSE; } - {COMMENT} { return COMMENT; } - {LINE_COMMENT} { return COMMENT; } - {ID} { return ID; } - "@\"" { yybegin(ID_STRING); } - {string_char}*"\"" { yybegin(YYINITIAL); return ID; } - [^] { yypushback(1); yybegin(UNCLOSED_STRING); } +//Keywords - "\"" { yybegin(STRING_LITERAL); } - {string_char}*"\"" { yybegin(YYINITIAL); return STRING_LITERAL_SINGLE; } - [^] { yypushback(1); yybegin(UNCLOSED_STRING); } + "false" { return KEYWORD_FALSE; } + "true" { return KEYWORD_TRUE; } + "null" { return KEYWORD_NULL; } + "nan" { return NUM_NAN; } + "inf" { return NUM_INF; } -[^\n]*{CRLF} { yybegin(YYINITIAL); return BAD_STRING; } +//Strings - {LINE_STRING} { return LINE_STRING; } + "'" { yybegin(CHAR_LIT); } + {char_char}*"'" { yybegin(YYINITIAL); return CHAR_LITERAL; } + <> { yybegin(YYINITIAL); return BAD_SQUOT; } + [^] { yypushback(1); yybegin(UNT_SQUOT); } + + "\"" { yybegin(STR_LIT); } + {string_char}*"\"" { yybegin(YYINITIAL); return STRING_LITERAL_SINGLE; } + <> { yybegin(YYINITIAL); return BAD_DQUOT; } + [^] { yypushback(1); yybegin(UNT_DQUOT); } + + "\\\\" { yybegin(STR_MULT_LINE); } + {all_nl_wrap} "\\\\" { } + {all_no_nl} { } + \n { yybegin(YYINITIAL); return STRING_LITERAL_MULTI; } + <> { yybegin(YYINITIAL); return STRING_LITERAL_MULTI; } + +//Numbers + + {FLOAT} { return FLOAT; } + {INTEGER} { return INTEGER; } + +//Identifiers + + {IDENTIFIER_PLAIN} { return IDENTIFIER; } + "@\"" { yybegin(ID_QUOT); } + {string_char}*"\"" { yybegin(YYINITIAL); return IDENTIFIER; } + <> { yybegin(YYINITIAL); return BAD_DQUOT; } + [^] { yypushback(1); yybegin(UNT_DQUOT); } + +//Error handling + + <> { yybegin(YYINITIAL); return BAD_SQUOT; } + {CRLF} { yybegin(YYINITIAL); return BAD_SQUOT; } + {all_no_nl} { } + <> { yybegin(YYINITIAL); return BAD_DQUOT; } + {CRLF} { yybegin(YYINITIAL); return BAD_DQUOT; } + {all_no_nl} { } + +//Misc + + {WHITE_SPACE} { return WHITE_SPACE; } [^] { return BAD_CHARACTER; } diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/comments/ZonCommenter.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/comments/ZonCommenter.kt index 0c40a90b..aaebf5ad 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/comments/ZonCommenter.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/comments/ZonCommenter.kt @@ -41,7 +41,7 @@ class ZonCommenter: CodeDocumentationAwareCommenter, IndentedCommenter { override fun forceIndentedLineComment() = true - override fun getLineCommentTokenType(): IElementType = ZonTypes.COMMENT + override fun getLineCommentTokenType(): IElementType = ZonTypes.LINE_COMMENT override fun getBlockCommentTokenType() = null diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/completion/ZonCompletionContributor.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/completion/ZonCompletionContributor.kt deleted file mode 100644 index 615b8645..00000000 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/completion/ZonCompletionContributor.kt +++ /dev/null @@ -1,146 +0,0 @@ -/* - * This file is part of ZigBrains. - * - * Copyright (C) 2023-2025 FalsePattern - * All Rights Reserved - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * ZigBrains is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, only version 3 of the License. - * - * ZigBrains is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with ZigBrains. If not, see . - */ - -package com.falsepattern.zigbrains.zon.completion - -import com.falsepattern.zigbrains.zon.psi.* -import com.intellij.codeInsight.completion.* -import com.intellij.codeInsight.lookup.LookupElementBuilder -import com.intellij.patterns.ElementPattern -import com.intellij.patterns.PlatformPatterns.psiElement -import com.intellij.patterns.PsiElementPattern -import com.intellij.psi.PsiElement -import com.intellij.psi.util.parentOfType -import com.intellij.util.ProcessingContext -import org.jetbrains.annotations.NonNls - -class ZonCompletionContributor : CompletionContributor() { - init { - extend( - CompletionType.BASIC, - psiElement() - .withParent(psiElement(ZonTypes.PROPERTY_PLACEHOLDER)) - .withSuperParent(4, psiOfType()) - ) { parameters, _, result -> - val placeholder = parameters.position.parentOfType() ?: return@extend - val zonEntry = placeholder.parentOfType() ?: return@extend - val keys = zonEntry.keys - doAddCompletions(placeholder.text.startsWith('.'), keys, ZON_ROOT_KEYS, result) - } - extend( - CompletionType.BASIC, - psiElement() - .withParent(psiElement(ZonTypes.VALUE_PLACEHOLDER)) - .withSuperParent(2, psiElement(ZonTypes.LIST)) - .withSuperParent(4, psiOfType()) - ) { _, _, result -> - doAddCompletions(false, emptySet(), ZON_ROOT_KEYS, result) - } - extend( - CompletionType.BASIC, - psiElement() - .withParent(psiElement(ZonTypes.PROPERTY_PLACEHOLDER)) - .withSuperParent(4, psiElement(ZonTypes.PROPERTY)) - .withSuperParent(7, psiElement(ZonTypes.PROPERTY)) - .withSuperParent(10, psiOfType()) - ) { parameters, _, result -> - val placeholder = parameters.position.parentOfType() ?: return@extend - val depEntry = placeholder.parentOfType() ?: return@extend - if (depEntry.isDependency) { - doAddCompletions(placeholder.text.startsWith('.'), emptySet(), ZON_DEP_KEYS, result) - } - } - extend( - CompletionType.BASIC, - psiElement() - .withParent(psiElement(ZonTypes.VALUE_PLACEHOLDER)) - .withSuperParent(2, psiElement(ZonTypes.LIST)) - .withSuperParent(4, psiElement(ZonTypes.PROPERTY)) - .withSuperParent(7, psiElement(ZonTypes.PROPERTY)) - .withSuperParent(10, psiOfType()) - ) {parameters, _, result -> - val placeholder = parameters.position.parentOfType() ?: return@extend - val depEntry = placeholder.parentOfType() ?: return@extend - if (depEntry.isDependency) { - doAddCompletions(false, emptySet(), ZON_DEP_KEYS, result) - } - } - extend( - CompletionType.BASIC, - psiElement() - .withParent(psiElement(ZonTypes.VALUE_PLACEHOLDER)) - .withSuperParent(5, psiElement(ZonTypes.PROPERTY)) - .withSuperParent(8, psiElement(ZonTypes.PROPERTY)) - .withSuperParent(11, psiOfType()) - ) { parameters, _, result -> - val placeholder = parameters.position.parentOfType() ?: return@extend - val valueProperty = placeholder.parentOfType() ?: return@extend - if (valueProperty.isDependency && valueProperty.identifier.value == "lazy") { - result.addElement(LookupElementBuilder.create("true")) - result.addElement(LookupElementBuilder.create("false")) - } - } - } - - private inline fun extend(type: CompletionType, place: ElementPattern, crossinline action: Processor) { - extend(type, place, object : CompletionProvider() { - override fun addCompletions( - parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet - ) = action(parameters, context, result) - }) - } -} - -private typealias Processor = ( - parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet -) -> Unit - -@NonNls -private val ZON_ROOT_KEYS: List = - listOf("name", "version", "minimum_zig_version", "dependencies", "paths") -@NonNls -private val ZON_DEP_KEYS: List = listOf("url", "hash", "path", "lazy") - -private fun doAddCompletions( - hasDot: Boolean, current: Set, expected: List, result: CompletionResultSet -) { - for (key in expected) { - if (current.contains(key)) { - continue - } - result.addElement(LookupElementBuilder.create(if (hasDot) key else ".$key")) - } -} - -private val ZonProperty.isDependency: Boolean - get() { - return parentOfType()?.isDependency == true - } - -private val ZonEntry.isDependency: Boolean - get() { - val parentProperty = parentOfType()?.parentOfType() ?: return false - return parentProperty.identifier.value == "dependencies" - } - -private inline fun psiOfType(): PsiElementPattern.Capture = - psiElement(T::class.java) \ No newline at end of file diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/folding/ZonFoldingBuilder.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/folding/ZonFoldingBuilder.kt deleted file mode 100644 index 82471cfc..00000000 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/folding/ZonFoldingBuilder.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of ZigBrains. - * - * Copyright (C) 2023-2025 FalsePattern - * All Rights Reserved - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * ZigBrains is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, only version 3 of the License. - * - * ZigBrains is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with ZigBrains. If not, see . - */ - -package com.falsepattern.zigbrains.zon.folding - -import com.falsepattern.zigbrains.zon.psi.ZonStruct -import com.falsepattern.zigbrains.zon.psi.ZonVisitor -import com.intellij.lang.ASTNode -import com.intellij.lang.folding.CustomFoldingBuilder -import com.intellij.lang.folding.FoldingDescriptor -import com.intellij.openapi.editor.Document -import com.intellij.openapi.project.DumbAware -import com.intellij.openapi.util.TextRange -import com.intellij.psi.PsiElement - -class ZonFoldingBuilder: CustomFoldingBuilder(), DumbAware { - override fun buildLanguageFoldRegions( - descriptors: MutableList, - root: PsiElement, - document: Document, - quick: Boolean - ) { - root.accept(object: ZonVisitor() { - override fun visitElement(element: PsiElement) { - super.visitElement(element) - element.acceptChildren(this) - } - - override fun visitStruct(o: ZonStruct) { - super.visitStruct(o) - descriptors.add(FoldingDescriptor(o, o.textRange)) - } - }) - } - - override fun getLanguagePlaceholderText(node: ASTNode, range: TextRange) = ".{...}" - - override fun isRegionCollapsedByDefault(node: ASTNode) = false -} \ No newline at end of file diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/formatter/ZonBlock.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/formatter/ZonBlock.kt index 5996625c..fa17c49f 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/formatter/ZonBlock.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/formatter/ZonBlock.kt @@ -27,14 +27,19 @@ import com.intellij.formatting.* import com.intellij.lang.ASTNode import com.intellij.psi.TokenType import com.intellij.psi.formatter.common.AbstractBlock +import com.intellij.psi.tree.IElementType class ZonBlock( node: ASTNode, wrap: Wrap?, alignment: Alignment?, - private val spacingBuilder: SpacingBuilder + val spacingBuilder: SpacingBuilder ) : AbstractBlock(node, wrap, alignment) { + override fun getSpacing(child1: Block?, child2: Block) = null + + override fun isLeaf() = myNode.firstChildNode == null + override fun buildChildren(): MutableList { val blocks = ArrayList() var child = myNode.firstChildNode @@ -44,33 +49,41 @@ class ZonBlock( } child = child.treeNext } + return blocks } - override fun getIndent(): Indent { - val parent = myNode.treeParent ?: return Indent.getNoneIndent() - val elementType = myNode.elementType - return if (parent.elementType == ZonTypes.ENTRY && - elementType != ZonTypes.DOT && - elementType != ZonTypes.LBRACE && - elementType != ZonTypes.RBRACE - ) { - Indent.getNormalIndent() - } else { - Indent.getNoneIndent() - } - } - - override fun getSpacing(child1: Block?, child2: Block) = null - - override fun isLeaf(): Boolean = myNode.firstChildNode == null - override fun getChildIndent(): Indent { - return if (myNode.elementType == ZonTypes.ENTRY) { - Indent.getNormalIndent() - } else { - Indent.getNoneIndent() - } + val node = this.node + return getIndentBasedOnParentType(node, null, node.elementType, PLACEHOLDER) } -} \ No newline at end of file + override fun getIndent(): Indent { + val node = this.node + val parent = node.treeParent ?: return noneIndent + return getIndentBasedOnParentType(parent, node, parent.elementType, node.elementType) + } +} +private fun getIndentBasedOnParentType( + parent: ASTNode, + child: ASTNode?, + parentType: IElementType, + childType: IElementType +): Indent { + //Struct/tuple initializers + if (parentType == ZonTypes.INIT_LIST && !childType.isBrace) + return normalIndent + + return noneIndent +} + +private val normalIndent: Indent get() = Indent.getNormalIndent() + +private val noneIndent: Indent get() = Indent.getNoneIndent() + +private val IElementType?.isBrace: Boolean + get() { + return this == ZonTypes.LBRACE || this == ZonTypes.RBRACE + } + +private val PLACEHOLDER = IElementType("placeholder", null) \ No newline at end of file diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/highlighting/ZonColorSettingsPage.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/highlighting/ZonColorSettingsPage.kt deleted file mode 100644 index 5354050b..00000000 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/highlighting/ZonColorSettingsPage.kt +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of ZigBrains. - * - * Copyright (C) 2023-2025 FalsePattern - * All Rights Reserved - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * ZigBrains is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, only version 3 of the License. - * - * ZigBrains is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with ZigBrains. If not, see . - */ - -package com.falsepattern.zigbrains.zon.highlighting - -import com.falsepattern.zigbrains.Icons -import com.falsepattern.zigbrains.ZigBrainsBundle -import com.intellij.openapi.options.colors.AttributesDescriptor -import com.intellij.openapi.options.colors.ColorDescriptor -import com.intellij.openapi.options.colors.ColorSettingsPage - -class ZonColorSettingsPage: ColorSettingsPage { - override fun getAttributeDescriptors() = DESCRIPTORS - - override fun getColorDescriptors(): Array = ColorDescriptor.EMPTY_ARRAY - - override fun getDisplayName() = ZigBrainsBundle.message("configurable.name.zon-color-settings-page") - - override fun getIcon() = Icons.Zon - - override fun getHighlighter() = ZonSyntaxHighlighter() - - override fun getDemoText() = """ - .{ - //This is an example file with some random data - .name = "zls", - .version = "0.11.0", - - .dependencies = .{ - .known_folders = .{ - .url = "https://github.com/ziglibs/known-folders/archive/fa75e1bc672952efa0cf06160bbd942b47f6d59b.tar.gz", - .hash = "122048992ca58a78318b6eba4f65c692564be5af3b30fbef50cd4abeda981b2e7fa5", - .lazy = true, - }, - .diffz = .{ - .url = "https://github.com/ziglibs/diffz/archive/90353d401c59e2ca5ed0abe5444c29ad3d7489aa.tar.gz", - .hash = "122089a8247a693cad53beb161bde6c30f71376cd4298798d45b32740c3581405864", - }, - .binned_allocator = .{ - .url = "https://gist.github.com/antlilja/8372900fcc09e38d7b0b6bbaddad3904/archive/6c3321e0969ff2463f8335da5601986cf2108690.tar.gz", - .hash = "1220363c7e27b2d3f39de6ff6e90f9537a0634199860fea237a55ddb1e1717f5d6a5", - }, - }, - .paths = .{""}, - } - """.trimIndent() - - override fun getAdditionalHighlightingTagToDescriptorMap() = null -} - -val DESCRIPTORS = arrayOf( - AttributesDescriptor(ZigBrainsBundle.message("zon.color-settings.eq"), ZonSyntaxHighlighter.EQ), - AttributesDescriptor(ZigBrainsBundle.message("zon.color-settings.id"), ZonSyntaxHighlighter.ID), - AttributesDescriptor(ZigBrainsBundle.message("zon.color-settings.comment"), ZonSyntaxHighlighter.COMMENT), - AttributesDescriptor(ZigBrainsBundle.message("zon.color-settings.bad_char"), ZonSyntaxHighlighter.BAD_CHAR), - AttributesDescriptor(ZigBrainsBundle.message("zon.color-settings.string"), ZonSyntaxHighlighter.STRING), - AttributesDescriptor(ZigBrainsBundle.message("zon.color-settings.comma"), ZonSyntaxHighlighter.COMMA), - AttributesDescriptor(ZigBrainsBundle.message("zon.color-settings.dot"), ZonSyntaxHighlighter.DOT), - AttributesDescriptor(ZigBrainsBundle.message("zon.color-settings.boolean"), ZonSyntaxHighlighter.BOOLEAN), - AttributesDescriptor(ZigBrainsBundle.message("zon.color-settings.brace"), ZonSyntaxHighlighter.BRACE) -) \ No newline at end of file diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/highlighting/ZonSyntaxHighlighter.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/highlighting/ZonSyntaxHighlighter.kt index d4b3dffc..f4324af0 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/highlighting/ZonSyntaxHighlighter.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/highlighting/ZonSyntaxHighlighter.kt @@ -22,54 +22,62 @@ package com.falsepattern.zigbrains.zon.highlighting +import com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter +import com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.Companion +import com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.Companion.BAD_CHAR +import com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.Companion.CHAR +import com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.Companion.COMMENT +import com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.Companion.KEYWORD +import com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.Companion.NUMBER +import com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.Companion.STRING +import com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.Companion.STRING_ESC_I_C +import com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.Companion.STRING_ESC_I_U +import com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.Companion.STRING_ESC_V +import com.falsepattern.zigbrains.zig.psi.ZigTypes +import com.falsepattern.zigbrains.zon.lexer.ZonHighlightingLexer import com.falsepattern.zigbrains.zon.lexer.ZonLexerAdapter import com.falsepattern.zigbrains.zon.psi.ZonTypes import com.intellij.openapi.editor.HighlighterColors import com.intellij.openapi.editor.colors.TextAttributesKey import com.intellij.openapi.fileTypes.SyntaxHighlighterBase +import com.intellij.psi.StringEscapesTokenTypes import com.intellij.psi.TokenType import com.intellij.psi.tree.IElementType import org.jetbrains.annotations.NonNls import com.intellij.openapi.editor.DefaultLanguageHighlighterColors as DefaultColors class ZonSyntaxHighlighter : SyntaxHighlighterBase() { - override fun getHighlightingLexer() = ZonLexerAdapter() + override fun getHighlightingLexer() = ZonHighlightingLexer() override fun getTokenHighlights(tokenType: IElementType?) = KEYMAP.getOrDefault(tokenType, EMPTY_KEYS) companion object { - // @formatter:off - val EQ = createKey("EQ" , DefaultColors.OPERATION_SIGN ) - val ID = createKey("ID" , DefaultColors.INSTANCE_FIELD ) - val COMMENT = createKey("COMMENT" , DefaultColors.LINE_COMMENT ) - val BAD_CHAR = createKey("BAD_CHARACTER", HighlighterColors.BAD_CHARACTER) - val STRING = createKey("STRING" , DefaultColors.STRING ) - val COMMA = createKey("COMMA" , DefaultColors.COMMA ) - val BOOLEAN = createKey("BOOLEAN" , DefaultColors.KEYWORD ) - val DOT = createKey("DOT" , DefaultColors.DOT ) - val BRACE = createKey("BRACE" , DefaultColors.BRACES ) - // @formatter:on - private val EMPTY_KEYS = emptyArray() private val KEYMAP = HashMap>() - private fun createKey(name: @NonNls String, fallback: TextAttributesKey) = - TextAttributesKey.createTextAttributesKey("ZON_$name", fallback) - private fun addMapping(key: TextAttributesKey, vararg types: IElementType) = types.forEach { KEYMAP[it] = arrayOf(key) } init { // @formatter:off - addMapping(DOT , ZonTypes.DOT) - addMapping(COMMA , ZonTypes.COMMA) - addMapping(BRACE , ZonTypes.LBRACE) - addMapping(BRACE , ZonTypes.RBRACE) - addMapping(STRING , ZonTypes.LINE_STRING, ZonTypes.STRING_LITERAL_SINGLE) + addMapping(COMMENT, ZonTypes.LINE_COMMENT) + addMapping( + KEYWORD, + *ZonTypes::class.java + .fields + .filter { + it.name.startsWith("KEYWORD_") + } + .map { it.get(null) as IElementType } + .toTypedArray() + ) + addMapping(STRING, ZonTypes.STRING_LITERAL_SINGLE, ZonTypes.STRING_LITERAL_MULTI, 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(COMMENT , ZonTypes.COMMENT) - addMapping(ID , ZonTypes.ID) - addMapping(EQ , ZonTypes.EQ) - addMapping(BOOLEAN , ZonTypes.BOOL_FALSE, ZonTypes.BOOL_TRUE) + addMapping(NUMBER, ZonTypes.INTEGER, ZonTypes.FLOAT, ZonTypes.NUM_NAN, ZonTypes.NUM_INF) + addMapping(CHAR, ZonTypes.CHAR_LITERAL, ZigTypes.CHAR_LITERAL) + // @formatter:on } } diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/impl/mixins/ZonEntryMixinImpl.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/lexer/ZonHighlightingLexer.kt similarity index 52% rename from core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/impl/mixins/ZonEntryMixinImpl.kt rename to core/src/main/kotlin/com/falsepattern/zigbrains/zon/lexer/ZonHighlightingLexer.kt index 4fa96526..6a76bdb6 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/impl/mixins/ZonEntryMixinImpl.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/lexer/ZonHighlightingLexer.kt @@ -20,15 +20,25 @@ * along with ZigBrains. If not, see . */ -package com.falsepattern.zigbrains.zon.psi.impl.mixins +package com.falsepattern.zigbrains.zon.lexer -import com.falsepattern.zigbrains.zon.psi.ZonEntry -import com.intellij.extapi.psi.ASTWrapperPsiElement -import com.intellij.lang.ASTNode +import com.falsepattern.zigbrains.zig.lexerstring.ZigLexerStringAdapter +import com.falsepattern.zigbrains.zig.psi.ZigTypes +import com.falsepattern.zigbrains.zon.psi.ZonTypes +import com.intellij.lexer.LayeredLexer +import com.intellij.lexer.MergingLexerAdapter +import com.intellij.psi.tree.IElementType +import com.intellij.psi.tree.TokenSet -abstract class ZonEntryMixinImpl(node: ASTNode): ASTWrapperPsiElement(node), ZonEntry { - override val keys: Set get() { - val struct = this.struct ?: return emptySet() - return struct.propertyList.map { it.identifier.value }.toSet() +class ZonHighlightingLexer: LayeredLexer(ZonLexerAdapter()) { + init { + registerSelfStoppingLayer( + MergingLexerAdapter( + ZigLexerStringAdapter(), + TokenSet.create(ZigTypes.STRING_LITERAL_SINGLE, ZigTypes.CHAR_LITERAL) + ), + arrayOf(ZonTypes.STRING_LITERAL_SINGLE, ZonTypes.CHAR_LITERAL), + IElementType.EMPTY_ARRAY + ) } } \ No newline at end of file diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/pairing/ZonBraceMatcher.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/pairing/ZonBraceMatcher.kt index 7d8ac0ac..a8854ab1 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/pairing/ZonBraceMatcher.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/pairing/ZonBraceMatcher.kt @@ -28,7 +28,7 @@ import com.intellij.lang.PairedBraceMatcher import com.intellij.psi.PsiFile import com.intellij.psi.tree.IElementType -class ZonBraceMatcher : PairedBraceMatcher { +class ZonBraceMatcher: PairedBraceMatcher { override fun getPairs() = PAIRS @@ -39,5 +39,5 @@ class ZonBraceMatcher : PairedBraceMatcher { file?.findElementAt(openingBraceOffset)?.parent?.textOffset ?: openingBraceOffset } -private val PAIR = BracePair(ZonTypes.LBRACE, ZonTypes.RBRACE, true) -private val PAIRS = arrayOf(PAIR) \ No newline at end of file +private val BRACE_PAIR = BracePair(ZonTypes.LBRACE, ZonTypes.RBRACE, true) +private val PAIRS = arrayOf(BRACE_PAIR) \ No newline at end of file diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/pairing/ZonQuoteHandler.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/pairing/ZonQuoteHandler.kt index 7e28bd10..10224e04 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/pairing/ZonQuoteHandler.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/pairing/ZonQuoteHandler.kt @@ -27,7 +27,10 @@ import com.intellij.codeInsight.editorActions.MultiCharQuoteHandler import com.intellij.codeInsight.editorActions.SimpleTokenSetQuoteHandler import com.intellij.openapi.editor.highlighter.HighlighterIterator -class ZonQuoteHandler: SimpleTokenSetQuoteHandler(ZonTypes.STRING_LITERAL_SINGLE, ZonTypes.BAD_STRING), MultiCharQuoteHandler { - override fun getClosingQuote(iterator: HighlighterIterator, offset: Int) = - "\"" +class ZonQuoteHandler: SimpleTokenSetQuoteHandler(ZonTypes.STRING_LITERAL_SINGLE, ZonTypes.IDENTIFIER, ZonTypes.BAD_DQUOT, ZonTypes.CHAR_LITERAL, ZonTypes.BAD_SQUOT), MultiCharQuoteHandler { + override fun getClosingQuote(iterator: HighlighterIterator, offset: Int) = when(iterator.tokenType) { + ZonTypes.STRING_LITERAL_SINGLE, ZonTypes.IDENTIFIER, ZonTypes.BAD_DQUOT -> "\"" + ZonTypes.CHAR_LITERAL, ZonTypes.BAD_SQUOT -> "'" + else -> null + } } \ No newline at end of file diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/parser/ZonTokenSets.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/parser/ZonTokenSets.kt index 5f0a19ab..3d8a4094 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/parser/ZonTokenSets.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/parser/ZonTokenSets.kt @@ -26,6 +26,6 @@ import com.falsepattern.zigbrains.zon.psi.ZonTypes import com.intellij.psi.tree.TokenSet object ZonTokenSets { - val COMMENTS = TokenSet.create(ZonTypes.COMMENT) - val STRINGS = TokenSet.create(ZonTypes.LINE_STRING, ZonTypes.STRING_LITERAL_SINGLE) + val COMMENTS = TokenSet.create(ZonTypes.LINE_COMMENT) + val STRINGS = TokenSet.create(ZonTypes.STRING_LITERAL_SINGLE, ZonTypes.STRING_LITERAL_MULTI) } \ No newline at end of file diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/impl/mixins/ZonIdentifierMixinImpl.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/impl/mixins/ZonIdentifierMixinImpl.kt deleted file mode 100644 index fab34d04..00000000 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/impl/mixins/ZonIdentifierMixinImpl.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of ZigBrains. - * - * Copyright (C) 2023-2025 FalsePattern - * All Rights Reserved - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * ZigBrains is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, only version 3 of the License. - * - * ZigBrains is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with ZigBrains. If not, see . - */ - -package com.falsepattern.zigbrains.zon.psi.impl.mixins - -import com.falsepattern.zigbrains.zon.psi.ZonIdentifier -import com.intellij.extapi.psi.ASTWrapperPsiElement -import com.intellij.lang.ASTNode - -abstract class ZonIdentifierMixinImpl(node: ASTNode): ASTWrapperPsiElement(node), ZonIdentifier { - override val value: String get() { - val text = this.text!! - return if (text.startsWith('@')) - text.substring(2, text.length - 1) - else - text - } -} diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/mixins/ZonEntryMixin.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/mixins/ZonEntryMixin.kt deleted file mode 100644 index 03a0507d..00000000 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/mixins/ZonEntryMixin.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of ZigBrains. - * - * Copyright (C) 2023-2025 FalsePattern - * All Rights Reserved - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * ZigBrains is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, only version 3 of the License. - * - * ZigBrains is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with ZigBrains. If not, see . - */ - -package com.falsepattern.zigbrains.zon.psi.mixins - -import com.intellij.psi.PsiElement - -interface ZonEntryMixin: PsiElement { - val keys: Set -} \ No newline at end of file diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/mixins/ZonIdentifierMixin.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/mixins/ZonIdentifierMixin.kt deleted file mode 100644 index a3a2fda4..00000000 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/zon/psi/mixins/ZonIdentifierMixin.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of ZigBrains. - * - * Copyright (C) 2023-2025 FalsePattern - * All Rights Reserved - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * ZigBrains is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, only version 3 of the License. - * - * ZigBrains is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with ZigBrains. If not, see . - */ - -package com.falsepattern.zigbrains.zon.psi.mixins - -import com.intellij.psi.PsiElement -import org.jetbrains.annotations.NonNls - -interface ZonIdentifierMixin: PsiElement { - val value: @NonNls String -} \ No newline at end of file diff --git a/core/src/main/resources/META-INF/zigbrains-core.xml b/core/src/main/resources/META-INF/zigbrains-core.xml index 0a005035..5c6a7f8b 100644 --- a/core/src/main/resources/META-INF/zigbrains-core.xml +++ b/core/src/main/resources/META-INF/zigbrains-core.xml @@ -64,11 +64,6 @@ - - - diff --git a/gradle.properties b/gradle.properties index e238ef1e..dbb4cf44 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ pluginName=ZigBrains pluginRepositoryUrl=https://github.com/FalsePattern/ZigBrains -pluginVersion=21.0.0 +pluginVersion=21.1.0 pluginSinceBuild=242 pluginUntilBuild=242.* diff --git a/lsp/src/main/resources/META-INF/zigbrains-lsp.xml b/lsp/src/main/resources/META-INF/zigbrains-lsp.xml index bc291342..5a749c2c 100644 --- a/lsp/src/main/resources/META-INF/zigbrains-lsp.xml +++ b/lsp/src/main/resources/META-INF/zigbrains-lsp.xml @@ -73,6 +73,11 @@ serverId="ZigBrains" languageId="zig" /> +