port the rest of the built-in zig features
This commit is contained in:
parent
d5fc288ffd
commit
19b0b09826
12 changed files with 520 additions and 12 deletions
|
@ -17,20 +17,22 @@ val rootPackagePath = "com/falsepattern/zigbrains/zig"
|
||||||
|
|
||||||
val parserDir = layout.buildDirectory.dir("$grammarGenRoot/parser")
|
val parserDir = layout.buildDirectory.dir("$grammarGenRoot/parser")
|
||||||
val lexerDir = layout.buildDirectory.dir("$grammarGenRoot/lexer")
|
val lexerDir = layout.buildDirectory.dir("$grammarGenRoot/lexer")
|
||||||
|
val lexerStringDir = layout.buildDirectory.dir("$grammarGenRoot/lexerstring")
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
java {
|
java {
|
||||||
srcDir(parserDir)
|
srcDir(parserDir)
|
||||||
srcDir(lexerDir)
|
srcDir(lexerDir)
|
||||||
|
srcDir(lexerStringDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
idea {
|
idea {
|
||||||
module {
|
module {
|
||||||
sourceDirs.addAll(listOf(parserDir.get().asFile, lexerDir.get().asFile))
|
sourceDirs.addAll(listOf(parserDir.get().asFile, lexerDir.get().asFile, lexerStringDir.get().asFile))
|
||||||
generatedSourceDirs.addAll(listOf(parserDir.get().asFile, lexerDir.get().asFile))
|
generatedSourceDirs.addAll(listOf(parserDir.get().asFile, lexerDir.get().asFile, lexerStringDir.get().asFile))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,10 +43,10 @@ tasks {
|
||||||
targetOutputDir = layout.buildDirectory.dir("$grammarGenRoot/lexer/$rootPackagePath/lexer")
|
targetOutputDir = layout.buildDirectory.dir("$grammarGenRoot/lexer/$rootPackagePath/lexer")
|
||||||
}
|
}
|
||||||
|
|
||||||
register<GenerateLexerTask>("generateStringLexer") {
|
register<GenerateLexerTask>("generateLexerString") {
|
||||||
purgeOldFiles = true
|
purgeOldFiles = true
|
||||||
sourceFile = file("src/main/grammar/ZigString.flex")
|
sourceFile = file("src/main/grammar/ZigString.flex")
|
||||||
targetOutputDir = layout.buildDirectory.dir("$grammarGenRoot/stringlexer/$rootPackagePath/stringlexer")
|
targetOutputDir = layout.buildDirectory.dir("$grammarGenRoot/lexerstring/$rootPackagePath/lexerstring")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +61,7 @@ tasks {
|
||||||
register<DefaultTask>("generateGrammars") {
|
register<DefaultTask>("generateGrammars") {
|
||||||
group = "grammarkit"
|
group = "grammarkit"
|
||||||
dependsOn("generateLexer")
|
dependsOn("generateLexer")
|
||||||
dependsOn("generateStringLexer")
|
dependsOn("generateLexerString")
|
||||||
dependsOn("generateParser")
|
dependsOn("generateParser")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package com.falsepattern.zigbrains.zig.stringlexer;
|
package com.falsepattern.zigbrains.zig.lexerstring;
|
||||||
|
|
||||||
import com.intellij.lexer.FlexLexer;
|
import com.intellij.lexer.FlexLexer;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
|
@ -26,15 +26,10 @@ import static com.intellij.psi.StringEscapesTokenTypes.*;
|
||||||
%%
|
%%
|
||||||
|
|
||||||
%public
|
%public
|
||||||
%class ZigStringLexer
|
%class ZigLexerString
|
||||||
%implements FlexLexer
|
%implements FlexLexer
|
||||||
%function advance
|
%function advance
|
||||||
%type IElementType
|
%type IElementType
|
||||||
%{
|
|
||||||
public ZigStringLexer() {
|
|
||||||
|
|
||||||
}
|
|
||||||
%}
|
|
||||||
|
|
||||||
hex=[0-9a-fA-F]
|
hex=[0-9a-fA-F]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.comments
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigTypes
|
||||||
|
import com.intellij.codeInsight.generation.IndentedCommenter
|
||||||
|
import com.intellij.lang.CodeDocumentationAwareCommenter
|
||||||
|
import com.intellij.psi.PsiComment
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
|
||||||
|
class ZigCommenter: CodeDocumentationAwareCommenter, IndentedCommenter {
|
||||||
|
override fun getLineCommentPrefix() = COMMENT
|
||||||
|
|
||||||
|
override fun getBlockCommentPrefix() = null
|
||||||
|
|
||||||
|
override fun getBlockCommentSuffix() = null
|
||||||
|
|
||||||
|
override fun getCommentedBlockCommentPrefix() = null
|
||||||
|
|
||||||
|
override fun getCommentedBlockCommentSuffix() = null
|
||||||
|
|
||||||
|
override fun forceIndentedLineComment() = true
|
||||||
|
|
||||||
|
override fun getLineCommentTokenType() = ZigTypes.LINE_COMMENT!!
|
||||||
|
|
||||||
|
override fun getBlockCommentTokenType() = null
|
||||||
|
|
||||||
|
override fun getDocumentationCommentTokenType() = ZigTypes.DOC_COMMENT!!
|
||||||
|
|
||||||
|
override fun getDocumentationCommentPrefix() = null
|
||||||
|
|
||||||
|
override fun getDocumentationCommentLinePrefix() = DOC_COMMENT
|
||||||
|
|
||||||
|
override fun getDocumentationCommentSuffix() = null
|
||||||
|
|
||||||
|
override fun isDocumentationComment(element: PsiComment?): Boolean {
|
||||||
|
val type = element?.tokenType ?: return false
|
||||||
|
return type == ZigTypes.DOC_COMMENT || type == ZigTypes.CONTAINER_DOC_COMMENT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const val COMMENT = "// "
|
||||||
|
const val DOC_COMMENT = "/// "
|
|
@ -0,0 +1,136 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.formatter
|
||||||
|
|
||||||
|
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
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigTypes.*
|
||||||
|
|
||||||
|
class ZigBlock(
|
||||||
|
node: ASTNode,
|
||||||
|
wrap: Wrap?,
|
||||||
|
alignment: Alignment?,
|
||||||
|
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<Block> {
|
||||||
|
val blocks = ArrayList<Block>()
|
||||||
|
var child = myNode.firstChildNode
|
||||||
|
while (child != null) {
|
||||||
|
if (child.elementType != TokenType.WHITE_SPACE) {
|
||||||
|
blocks.add(ZigBlock(child, null, null, spacingBuilder))
|
||||||
|
}
|
||||||
|
child = child.treeNext
|
||||||
|
}
|
||||||
|
|
||||||
|
return blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getChildIndent(): Indent {
|
||||||
|
val node = this.node
|
||||||
|
return getIndentBasedOnParentType(node, null, node.elementType, PLACEHOLDER)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
//Statement blocks
|
||||||
|
if (parentType == BLOCK && !childType.isBrace)
|
||||||
|
return normalIndent
|
||||||
|
|
||||||
|
//Struct/tuple initializers
|
||||||
|
if (parentType == INIT_LIST && !childType.isBrace)
|
||||||
|
return normalIndent
|
||||||
|
|
||||||
|
//Function call args
|
||||||
|
if (parentType == EXPR_LIST ||
|
||||||
|
parentType == FN_CALL_ARGUMENTS && childType === PLACEHOLDER
|
||||||
|
)
|
||||||
|
return normalIndent
|
||||||
|
|
||||||
|
//Function declaration parameters
|
||||||
|
if (parentType == PARAM_DECL_LIST ||
|
||||||
|
parentType == FN_PROTO && childType === PLACEHOLDER
|
||||||
|
)
|
||||||
|
return normalIndent
|
||||||
|
|
||||||
|
//Chained operations on newlines
|
||||||
|
if ((parentType == BOOL_OR_EXPR ||
|
||||||
|
parentType == BOOL_AND_EXPR ||
|
||||||
|
parentType == COMPARE_EXPR ||
|
||||||
|
parentType == BITWISE_EXPR ||
|
||||||
|
parentType == BIT_SHIFT_EXPR ||
|
||||||
|
parentType == ADDITION_EXPR ||
|
||||||
|
parentType == MULTIPLY_EXPR) &&
|
||||||
|
parent.firstChildNode != child
|
||||||
|
)
|
||||||
|
return normalIndent
|
||||||
|
|
||||||
|
//Switch prongs
|
||||||
|
if (parentType == SWITCH_PRONG_LIST ||
|
||||||
|
parentType == SWITCH_EXPR && childType == PLACEHOLDER
|
||||||
|
)
|
||||||
|
return normalIndent
|
||||||
|
|
||||||
|
//If expressions/statements
|
||||||
|
if ((parentType == IF_EXPR ||
|
||||||
|
parentType == IF_STATEMENT) &&
|
||||||
|
childType != KEYWORD_ELSE &&
|
||||||
|
childType != IF_PREFIX
|
||||||
|
)
|
||||||
|
return normalIndent
|
||||||
|
|
||||||
|
//Struct members
|
||||||
|
if (parentType == CONTAINER_DECL_AUTO &&
|
||||||
|
childType != CONTAINER_DECL_TYPE &&
|
||||||
|
childType != CONTAINER_DOC_COMMENT &&
|
||||||
|
!childType.isBrace
|
||||||
|
)
|
||||||
|
return normalIndent
|
||||||
|
|
||||||
|
//Inline assembly body
|
||||||
|
if (parentType == ASM_EXPR &&
|
||||||
|
childType != KEYWORD_ASM &&
|
||||||
|
childType != KEYWORD_VOLATILE &&
|
||||||
|
!childType.isParen)
|
||||||
|
return normalIndent
|
||||||
|
|
||||||
|
//Assembly params
|
||||||
|
if (parentType == ASM_INPUT_LIST || parentType == ASM_OUTPUT_LIST)
|
||||||
|
return spaceIndent(2)
|
||||||
|
|
||||||
|
return noneIndent
|
||||||
|
}
|
||||||
|
|
||||||
|
private val normalIndent: Indent get() = Indent.getNormalIndent()
|
||||||
|
|
||||||
|
private fun spaceIndent(spaces: Int) = Indent.getSpaceIndent(2)
|
||||||
|
|
||||||
|
private val noneIndent: Indent get() = Indent.getNoneIndent()
|
||||||
|
|
||||||
|
private val IElementType?.isBrace: Boolean
|
||||||
|
get() {
|
||||||
|
return this == LBRACE || this == RBRACE
|
||||||
|
}
|
||||||
|
|
||||||
|
private val IElementType?.isParen: Boolean
|
||||||
|
get() {
|
||||||
|
return this == LPAREN || this == RPAREN
|
||||||
|
}
|
||||||
|
|
||||||
|
private val PLACEHOLDER = IElementType("placeholder", null)
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.formatter
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zig.ZigLanguage
|
||||||
|
import com.intellij.formatting.*
|
||||||
|
|
||||||
|
class ZigFormattingModelBuilder: FormattingModelBuilder {
|
||||||
|
override fun createModel(context: FormattingContext): FormattingModel {
|
||||||
|
val settings = context.codeStyleSettings
|
||||||
|
return FormattingModelProvider.createFormattingModelForPsiFile(
|
||||||
|
context.containingFile,
|
||||||
|
ZigBlock(context.node, null, null, SpacingBuilder(settings, ZigLanguage)),
|
||||||
|
settings
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.highlighter
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zig.Icons
|
||||||
|
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||||
|
import com.intellij.openapi.options.colors.AttributesDescriptor
|
||||||
|
import com.intellij.openapi.options.colors.ColorDescriptor
|
||||||
|
import com.intellij.openapi.options.colors.ColorSettingsPage
|
||||||
|
import kotlinx.collections.immutable.toImmutableMap
|
||||||
|
|
||||||
|
|
||||||
|
class ZigColorSettingsPage: ColorSettingsPage {
|
||||||
|
override fun getAttributeDescriptors() = DESCRIPTORS
|
||||||
|
|
||||||
|
override fun getColorDescriptors(): Array<ColorDescriptor> = ColorDescriptor.EMPTY_ARRAY
|
||||||
|
|
||||||
|
override fun getDisplayName() = "Zig"
|
||||||
|
|
||||||
|
override fun getIcon() = Icons.ZIG
|
||||||
|
|
||||||
|
override fun getHighlighter() = ZigSyntaxHighlighter()
|
||||||
|
|
||||||
|
override fun getDemoText() = """
|
||||||
|
///This is a documentation comment
|
||||||
|
const <ns_decl>std</ns_decl> = @import("std");
|
||||||
|
|
||||||
|
const <enum_decl>AnEnum</enum_decl> = enum {
|
||||||
|
<enum_member_decl>A</enum_member_decl>,
|
||||||
|
<enum_member_decl>B</enum_member_decl>,
|
||||||
|
<enum_member_decl>C</enum_member_decl>,
|
||||||
|
};
|
||||||
|
|
||||||
|
const <struct_decl>AStruct</struct_decl> = struct {
|
||||||
|
<property_decl>fieldA</property_decl>: <type>u32</type>,
|
||||||
|
<property_decl>fieldB</property_decl>: <type>u16</type>
|
||||||
|
};
|
||||||
|
|
||||||
|
const <type_decl>AnError</type_decl> = error {
|
||||||
|
<error_tag_decl>SomeError</error_tag_decl>
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn <function_decl>main</function_decl>() <type>AnError</type>.<error_tag>SomeError</error_tag>!<type>void</type> {
|
||||||
|
// Prints to stderr (it's a shortcut based on `std.io.getStdErr()`)
|
||||||
|
<namespace>std</namespace>.<namespace>debug</namespace>.<function>print</function>("All your {s} are belong to us.\n", .{"codebase"});
|
||||||
|
|
||||||
|
// stdout is for the actual output of your application, for example if you
|
||||||
|
// are implementing gzip, then only the compressed bytes should be sent to
|
||||||
|
// stdout, not any debugging messages.
|
||||||
|
const <variable_decl>stdout_file</variable_decl> = <namespace>std</namespace>.<namespace>io</namespace>.<function>getStdOut</function>().<method>writer</method>();
|
||||||
|
var <variable_decl>bw</variable_decl> = <namespace>std</namespace>.<namespace>io</namespace>.<function>bufferedWriter</function>(<variable>stdout_file</variable>);
|
||||||
|
const <variable_decl>stdout</variable_decl> = <variable>bw</variable>.<method>writer</method>();
|
||||||
|
|
||||||
|
try <variable>stdout</variable>.<method>print</method>(\\Run `zig build test` to run the tests.
|
||||||
|
\\
|
||||||
|
, .{});
|
||||||
|
|
||||||
|
_ = <enum>AnEnum</enum>.<enum_member>A</enum_member>;
|
||||||
|
|
||||||
|
try <variable>bw</variable>.<method>flush</method>(); // don't forget to flush!
|
||||||
|
}
|
||||||
|
|
||||||
|
test "simple test" {
|
||||||
|
var <variable_decl>list</variable_decl> = <namespace>std</namespace>.<type>ArrayList</type>(<type>i32</type>).<function>init</function>(<namespace>std</namespace>.<namespace>testing</namespace>.<variable>allocator</variable>);
|
||||||
|
defer <variable>list</variable>.<method>deinit</method>(); // try commenting this out and see if zig detects the memory leak!
|
||||||
|
try <variable>list</variable>.<method>append</method>(42);
|
||||||
|
try <namespace>std</namespace>.<namespace>testing</namespace>.<method_gen>expectEqual</method_gen>(@as(<type>i32</type>, 42), <variable>list</variable>.<method>pop</method>());
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
override fun getAdditionalHighlightingTagToDescriptorMap() =
|
||||||
|
ADD_HIGHLIGHT
|
||||||
|
}
|
||||||
|
|
||||||
|
private val ADD_HIGHLIGHT = HashMap<String, TextAttributesKey>().apply {
|
||||||
|
this["enum"] = ZigSyntaxHighlighter.ENUM_REF
|
||||||
|
this["enum_decl"] = ZigSyntaxHighlighter.ENUM_DECL
|
||||||
|
this["enum_member"] = ZigSyntaxHighlighter.ENUM_MEMBER_REF
|
||||||
|
this["enum_member_decl"] = ZigSyntaxHighlighter.ENUM_MEMBER_DECL
|
||||||
|
this["error_tag"] = ZigSyntaxHighlighter.ERROR_TAG_REF
|
||||||
|
this["error_tag_decl"] = ZigSyntaxHighlighter.ERROR_TAG_DECL
|
||||||
|
this["function"] = ZigSyntaxHighlighter.FUNCTION_REF
|
||||||
|
this["function_decl"] = ZigSyntaxHighlighter.FUNCTION_DECL
|
||||||
|
this["method"] = ZigSyntaxHighlighter.METHOD_REF
|
||||||
|
this["method_gen"] = ZigSyntaxHighlighter.METHOD_REF_GEN
|
||||||
|
this["namespace"] = ZigSyntaxHighlighter.NAMESPACE_REF
|
||||||
|
this["property_decl"] = ZigSyntaxHighlighter.PROPERTY_DECL
|
||||||
|
this["struct"] = ZigSyntaxHighlighter.STRUCT_REF
|
||||||
|
this["struct_decl"] = ZigSyntaxHighlighter.STRUCT_DECL
|
||||||
|
this["type"] = ZigSyntaxHighlighter.TYPE_REF
|
||||||
|
this["type_decl"] = ZigSyntaxHighlighter.TYPE_DECL
|
||||||
|
this["variable"] = ZigSyntaxHighlighter.VARIABLE_REF
|
||||||
|
this["variable_decl"] = ZigSyntaxHighlighter.VARIABLE_DECL
|
||||||
|
}.toImmutableMap()
|
||||||
|
|
||||||
|
private val DESCRIPTORS: Array<AttributesDescriptor> = arrayOf(
|
||||||
|
AttributesDescriptor("Bad character", ZigSyntaxHighlighter.BAD_CHAR),
|
||||||
|
AttributesDescriptor("Builtin", ZigSyntaxHighlighter.BUILTIN),
|
||||||
|
AttributesDescriptor("Character literal", ZigSyntaxHighlighter.CHAR),
|
||||||
|
AttributesDescriptor("Comment//Regular", ZigSyntaxHighlighter.COMMENT),
|
||||||
|
AttributesDescriptor("Comment//Documentation", ZigSyntaxHighlighter.COMMENT_DOC),
|
||||||
|
AttributesDescriptor("Enum//Reference", ZigSyntaxHighlighter.ENUM_REF),
|
||||||
|
AttributesDescriptor("Enum//Declaration", ZigSyntaxHighlighter.ENUM_DECL),
|
||||||
|
AttributesDescriptor("Enum//Member//Declaration", ZigSyntaxHighlighter.ENUM_MEMBER_DECL),
|
||||||
|
AttributesDescriptor("Enum//Member//Reference", ZigSyntaxHighlighter.ENUM_MEMBER_REF),
|
||||||
|
AttributesDescriptor("Error tag//Declaration", ZigSyntaxHighlighter.ERROR_TAG_DECL),
|
||||||
|
AttributesDescriptor("Error tag//Reference", ZigSyntaxHighlighter.ERROR_TAG_REF),
|
||||||
|
AttributesDescriptor("Function//Declaration", ZigSyntaxHighlighter.FUNCTION_DECL),
|
||||||
|
AttributesDescriptor("Function//Declaration//Generic", ZigSyntaxHighlighter.FUNCTION_DECL_GEN),
|
||||||
|
AttributesDescriptor("Function//Reference", ZigSyntaxHighlighter.FUNCTION_REF),
|
||||||
|
AttributesDescriptor("Function//Reference//Generic", ZigSyntaxHighlighter.FUNCTION_REF_GEN),
|
||||||
|
AttributesDescriptor("Keyword", ZigSyntaxHighlighter.KEYWORD),
|
||||||
|
AttributesDescriptor("Label//Declaration", ZigSyntaxHighlighter.LABEL_REF),
|
||||||
|
AttributesDescriptor("Label//Reference", ZigSyntaxHighlighter.LABEL_REF),
|
||||||
|
AttributesDescriptor("Method//Declaration", ZigSyntaxHighlighter.METHOD_DECL),
|
||||||
|
AttributesDescriptor("Method//Declaration//Generic", ZigSyntaxHighlighter.METHOD_DECL_GEN),
|
||||||
|
AttributesDescriptor("Method//Reference", ZigSyntaxHighlighter.METHOD_REF),
|
||||||
|
AttributesDescriptor("Method//Reference//Generic", ZigSyntaxHighlighter.METHOD_REF_GEN),
|
||||||
|
AttributesDescriptor("Namespace//Declaration", ZigSyntaxHighlighter.NAMESPACE_DECL),
|
||||||
|
AttributesDescriptor("Namespace//Reference", ZigSyntaxHighlighter.NAMESPACE_REF),
|
||||||
|
AttributesDescriptor("Number", ZigSyntaxHighlighter.NUMBER),
|
||||||
|
AttributesDescriptor("Operator", ZigSyntaxHighlighter.OPERATOR),
|
||||||
|
AttributesDescriptor("Parameter", ZigSyntaxHighlighter.PARAMETER),
|
||||||
|
AttributesDescriptor("Property//Declaration", ZigSyntaxHighlighter.PROPERTY_DECL),
|
||||||
|
AttributesDescriptor("Property//Reference", ZigSyntaxHighlighter.PROPERTY_REF),
|
||||||
|
AttributesDescriptor("String", ZigSyntaxHighlighter.STRING),
|
||||||
|
AttributesDescriptor("String//Escape", ZigSyntaxHighlighter.STRING_ESC_V),
|
||||||
|
AttributesDescriptor("String//Escape//Invalid char", ZigSyntaxHighlighter.STRING_ESC_I_C),
|
||||||
|
AttributesDescriptor("String//Escape//Invalid unicode", ZigSyntaxHighlighter.STRING_ESC_I_U),
|
||||||
|
AttributesDescriptor("Struct//Declaration", ZigSyntaxHighlighter.STRUCT_DECL),
|
||||||
|
AttributesDescriptor("Struct//Reference", ZigSyntaxHighlighter.STRUCT_REF),
|
||||||
|
AttributesDescriptor("Type//Declaration", ZigSyntaxHighlighter.TYPE_DECL),
|
||||||
|
AttributesDescriptor("Type//Declaration//Generic", ZigSyntaxHighlighter.TYPE_DECL_GEN),
|
||||||
|
AttributesDescriptor("Type//Reference", ZigSyntaxHighlighter.TYPE_REF),
|
||||||
|
AttributesDescriptor("Type//Reference//Generic", ZigSyntaxHighlighter.TYPE_REF_GEN),
|
||||||
|
AttributesDescriptor("Type parameter//Reference", ZigSyntaxHighlighter.TYPE_PARAM),
|
||||||
|
AttributesDescriptor("Type parameter//Declaration", ZigSyntaxHighlighter.TYPE_PARAM_DECL),
|
||||||
|
AttributesDescriptor("Variable//Declaration", ZigSyntaxHighlighter.VARIABLE_DECL),
|
||||||
|
AttributesDescriptor("Variable//Declaration//Deprecated", ZigSyntaxHighlighter.VARIABLE_DECL_DEPR),
|
||||||
|
AttributesDescriptor("Variable//Reference", ZigSyntaxHighlighter.VARIABLE_REF),
|
||||||
|
AttributesDescriptor("Variable//Reference//Deprecated", ZigSyntaxHighlighter.VARIABLE_REF_DEPR),
|
||||||
|
)
|
|
@ -0,0 +1,104 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.highlighter
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zig.lexer.ZigHighlightingLexer
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigTypes
|
||||||
|
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
|
||||||
|
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
|
||||||
|
|
||||||
|
class ZigSyntaxHighlighter: SyntaxHighlighterBase() {
|
||||||
|
override fun getHighlightingLexer() = ZigHighlightingLexer()
|
||||||
|
|
||||||
|
override fun getTokenHighlights(tokenType: IElementType?) =
|
||||||
|
KEYMAP.getOrDefault(tokenType, EMPTY_KEYS)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
val BAD_CHAR = createKey("BAD_CHARACTER" , HighlighterColors.BAD_CHARACTER )
|
||||||
|
val BUILTIN = createKey("BUILTIN" , DefaultLanguageHighlighterColors.STATIC_METHOD )
|
||||||
|
val CHAR = createKey("CHAR" , DefaultLanguageHighlighterColors.NUMBER )
|
||||||
|
val COMMENT = createKey("COMMENT" , DefaultLanguageHighlighterColors.LINE_COMMENT )
|
||||||
|
val COMMENT_DOC = createKey("COMMENT_DOC" , DefaultLanguageHighlighterColors.DOC_COMMENT )
|
||||||
|
val ENUM_DECL = createKey("ENUM_DECL" , DefaultLanguageHighlighterColors.CLASS_NAME )
|
||||||
|
val ENUM_REF = createKey("ENUM" , DefaultLanguageHighlighterColors.CLASS_REFERENCE )
|
||||||
|
val ENUM_MEMBER_DECL = createKey("ENUM_MEMBER_DECL" , DefaultLanguageHighlighterColors.STATIC_FIELD )
|
||||||
|
val ENUM_MEMBER_REF = createKey("ENUM_MEMBER" , ENUM_MEMBER_DECL )
|
||||||
|
val ERROR_TAG_DECL = createKey("ERROR_TAG_DECL" , DefaultLanguageHighlighterColors.STATIC_FIELD )
|
||||||
|
val ERROR_TAG_REF = createKey("ERROR_TAG" , ERROR_TAG_DECL )
|
||||||
|
val PROPERTY_DECL = createKey("PROPERTY_DECL" , DefaultLanguageHighlighterColors.STATIC_FIELD )
|
||||||
|
val PROPERTY_REF = createKey("PROPERTY" , PROPERTY_DECL )
|
||||||
|
val FUNCTION_DECL = createKey("FUNCTION_DECL" , DefaultLanguageHighlighterColors.FUNCTION_DECLARATION )
|
||||||
|
val FUNCTION_DECL_GEN = createKey("FUNCTION_DECL_GEN" , FUNCTION_DECL )
|
||||||
|
val FUNCTION_REF = createKey("FUNCTION" , DefaultLanguageHighlighterColors.FUNCTION_CALL )
|
||||||
|
val FUNCTION_REF_GEN = createKey("FUNCTION_GEN" , FUNCTION_REF )
|
||||||
|
val KEYWORD = createKey("KEYWORD" , DefaultLanguageHighlighterColors.KEYWORD )
|
||||||
|
val LABEL_DECL = createKey("LABEL_DECL" , DefaultLanguageHighlighterColors.LABEL )
|
||||||
|
val LABEL_REF = createKey("LABEL" , LABEL_DECL )
|
||||||
|
val METHOD_DECL = createKey("METHOD_DECL" , FUNCTION_DECL )
|
||||||
|
val METHOD_DECL_GEN = createKey("METHOD_DECL_GEN" , METHOD_DECL )
|
||||||
|
val METHOD_REF = createKey("METHOD" , FUNCTION_REF )
|
||||||
|
val METHOD_REF_GEN = createKey("METHOD_GEN" , METHOD_REF )
|
||||||
|
val NAMESPACE_DECL = createKey("NAMESPACE_DECL" , DefaultLanguageHighlighterColors.CLASS_NAME )
|
||||||
|
val NAMESPACE_REF = createKey("NAMESPACE" , DefaultLanguageHighlighterColors.CLASS_REFERENCE )
|
||||||
|
val NUMBER = createKey("NUMBER" , DefaultLanguageHighlighterColors.NUMBER )
|
||||||
|
val OPERATOR = createKey("OPERATOR" , DefaultLanguageHighlighterColors.OPERATION_SIGN )
|
||||||
|
val PARAMETER = createKey("PARAMETER" , DefaultLanguageHighlighterColors.PARAMETER )
|
||||||
|
val STRING = createKey("STRING" , DefaultLanguageHighlighterColors.STRING )
|
||||||
|
val STRING_ESC_V = createKey("STRING_ESC_V" , DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE )
|
||||||
|
val STRING_ESC_I_C = createKey("STRING_ESC_I_C" , DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE )
|
||||||
|
val STRING_ESC_I_U = createKey("STRING_ESC_I_U" , DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE )
|
||||||
|
val STRUCT_DECL = createKey("STRUCT_DECL" , DefaultLanguageHighlighterColors.CLASS_NAME )
|
||||||
|
val STRUCT_REF = createKey("STRUCT" , DefaultLanguageHighlighterColors.CLASS_REFERENCE )
|
||||||
|
val TYPE_DECL = createKey("TYPE_DECL" , DefaultLanguageHighlighterColors.CLASS_NAME )
|
||||||
|
val TYPE_DECL_GEN = createKey("TYPE_DECL_GEN" , TYPE_DECL )
|
||||||
|
val TYPE_REF = createKey("TYPE" , DefaultLanguageHighlighterColors.CLASS_REFERENCE )
|
||||||
|
val TYPE_REF_GEN = createKey("TYPE_GEN" , TYPE_REF )
|
||||||
|
val TYPE_PARAM = createKey("TYPE_PARAM" , DefaultLanguageHighlighterColors.PARAMETER )
|
||||||
|
val TYPE_PARAM_DECL = createKey("TYPE_PARAM_DECL" , TYPE_PARAM )
|
||||||
|
val VARIABLE_DECL = createKey("VARIABLE_DECL" , DefaultLanguageHighlighterColors.LOCAL_VARIABLE )
|
||||||
|
val VARIABLE_DECL_DEPR= createKey("VARIABLE_DECL_DEPR" , VARIABLE_DECL )
|
||||||
|
val VARIABLE_REF = createKey("VARIABLE" , VARIABLE_DECL )
|
||||||
|
val VARIABLE_REF_DEPR = createKey("VARIABLE_REF_DEPL" , VARIABLE_REF )
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
private val EMPTY_KEYS = arrayOf<TextAttributesKey>()
|
||||||
|
private val KEYMAP = HashMap<IElementType, Array<TextAttributesKey>>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
addMapping(COMMENT, ZigTypes.LINE_COMMENT)
|
||||||
|
addMapping(COMMENT_DOC, ZigTypes.DOC_COMMENT, ZigTypes.CONTAINER_DOC_COMMENT)
|
||||||
|
|
||||||
|
addMapping(
|
||||||
|
KEYWORD,
|
||||||
|
*ZigTypes::class.java
|
||||||
|
.fields
|
||||||
|
.filter { it.name.startsWith("KEYWORD_") }
|
||||||
|
.map { it.get(null) as IElementType }
|
||||||
|
.toTypedArray()
|
||||||
|
)
|
||||||
|
addMapping(BUILTIN, ZigTypes.BUILTINIDENTIFIER)
|
||||||
|
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(NUMBER, ZigTypes.INTEGER, ZigTypes.FLOAT)
|
||||||
|
addMapping(CHAR, ZigTypes.CHAR_LITERAL)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addMapping(key: TextAttributesKey, vararg types: IElementType) {
|
||||||
|
val a = arrayOf(key)
|
||||||
|
for (type in types) {
|
||||||
|
KEYMAP[type] = a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createKey(name: String, fallback: TextAttributesKey) =
|
||||||
|
TextAttributesKey.createTextAttributesKey("ZIG_$name", fallback)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.highlighter
|
||||||
|
|
||||||
|
import com.intellij.openapi.fileTypes.SyntaxHighlighter
|
||||||
|
import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
|
||||||
|
class ZigSyntaxHighlighterFactory: SyntaxHighlighterFactory() {
|
||||||
|
override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?) =
|
||||||
|
ZigSyntaxHighlighter()
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.lexer
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zig.lexerstring.ZigLexerStringAdapter
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigTypes
|
||||||
|
import com.intellij.lexer.LayeredLexer
|
||||||
|
import com.intellij.lexer.MergingLexerAdapter
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
import com.intellij.psi.tree.TokenSet
|
||||||
|
|
||||||
|
class ZigHighlightingLexer: LayeredLexer(ZigLexerAdapter()) {
|
||||||
|
init {
|
||||||
|
registerSelfStoppingLayer(
|
||||||
|
MergingLexerAdapter(
|
||||||
|
ZigLexerStringAdapter(),
|
||||||
|
TokenSet.create(ZigTypes.STRING_LITERAL_SINGLE)
|
||||||
|
),
|
||||||
|
arrayOf(ZigTypes.STRING_LITERAL_SINGLE),
|
||||||
|
IElementType.EMPTY_ARRAY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.lexerstring
|
||||||
|
|
||||||
|
import com.intellij.lexer.FlexAdapter
|
||||||
|
|
||||||
|
class ZigLexerStringAdapter: FlexAdapter(ZigLexerString(null)) {
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.pairing
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigTypes
|
||||||
|
import com.intellij.lang.BracePair
|
||||||
|
import com.intellij.lang.PairedBraceMatcher
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
|
||||||
|
class ZigBraceMatcher: PairedBraceMatcher {
|
||||||
|
override fun getPairs() =
|
||||||
|
PAIRS
|
||||||
|
|
||||||
|
override fun isPairedBracesAllowedBeforeType(lbraceType: IElementType, contextType: IElementType?) =
|
||||||
|
true
|
||||||
|
|
||||||
|
override fun getCodeConstructStart(file: PsiFile?, openingBraceOffset: Int) =
|
||||||
|
file?.findElementAt(openingBraceOffset)?.parent?.textOffset ?: openingBraceOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
private val BRACE_PAIR = BracePair(ZigTypes.LBRACE, ZigTypes.RBRACE, true)
|
||||||
|
private val PAREN_PAIR = BracePair(ZigTypes.LPAREN, ZigTypes.RPAREN, false)
|
||||||
|
private val BRACKET_PAIR = BracePair(ZigTypes.LBRACKET, ZigTypes.RBRACKET, false)
|
||||||
|
private val PAIRS = arrayOf(BRACE_PAIR, PAREN_PAIR, BRACKET_PAIR)
|
|
@ -7,15 +7,29 @@
|
||||||
|
|
||||||
<!-- region Zig -->
|
<!-- region Zig -->
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
|
<colorSettingsPage
|
||||||
|
implementation="com.falsepattern.zigbrains.zig.highlighter.ZigColorSettingsPage"/>
|
||||||
<fileType
|
<fileType
|
||||||
name="Zig File"
|
name="Zig File"
|
||||||
implementationClass="com.falsepattern.zigbrains.zig.ZigFileType"
|
implementationClass="com.falsepattern.zigbrains.zig.ZigFileType"
|
||||||
fieldName="INSTANCE"
|
fieldName="INSTANCE"
|
||||||
language="Zig"
|
language="Zig"
|
||||||
extensions="zig"/>
|
extensions="zig"/>
|
||||||
|
<lang.braceMatcher
|
||||||
|
language="Zig"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zig.pairing.ZigBraceMatcher"/>
|
||||||
|
<lang.commenter
|
||||||
|
language="Zig"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zig.comments.ZigCommenter"/>
|
||||||
|
<lang.formatter
|
||||||
|
language="Zig"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zig.formatter.ZigFormattingModelBuilder"/>
|
||||||
<lang.parserDefinition
|
<lang.parserDefinition
|
||||||
language="Zig"
|
language="Zig"
|
||||||
implementationClass="com.falsepattern.zigbrains.zig.parser.ZigParserDefinition"/>
|
implementationClass="com.falsepattern.zigbrains.zig.parser.ZigParserDefinition"/>
|
||||||
|
<lang.syntaxHighlighterFactory
|
||||||
|
language="Zig"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighterFactory"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
<!-- endregion Zig -->
|
<!-- endregion Zig -->
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue