IntelliJ平台插件开发:超过4字符的关键字语法高亮失效问题
免责声明
本问题主要面向至少具备IntelliJ平台插件开发基础知识的人员。
为了入门插件开发,我决定开发一款对.mcfunction代码(Minecraft指令)进行高亮的插件。
我的代码在关键字长度小于5个字符时运行完全正常,但长度超过4个字符的关键字只有在重载文件后才会被高亮。
问题演示
- 输入时的代码状态
- 重载文件后的代码状态
除了重载文件外未做任何操作。该问题仅出现在长度超过4字符的关键字上。在以下示例中,function和test使用完全相同的语法高亮逻辑:
- 输入时的代码状态
- 注释再取消注释也可修复高亮问题
- 正确的高亮效果
相关代码
JFlex文件 Minecraft.flex 内容
package org.intellij.sdk.language; import com.intellij.lexer.FlexLexer; import com.intellij.psi.tree.IElementType; import org.intellij.sdk.language.psi.MinecraftTypes; import com.intellij.psi.TokenType; %% %class MinecraftLexer %implements FlexLexer %unicode %function advance %type IElementType WHITE_SPACE=[ \t\n\r]+ END_OF_LINE_COMMENT=("#")[^\r\n]* COMMAND=execute|function|test ARGUMENT=at|as|run SELECTOR=@e|@a|@p|@s %% <YYINITIAL> { {WHITE_SPACE} { return TokenType.WHITE_SPACE; } {END_OF_LINE_COMMENT} { return MinecraftTypes.COMMENT; } {COMMAND} { return MinecraftTypes.COMMAND; } {ARGUMENT} { return MinecraftTypes.ARGUMENT; } {SELECTOR} { return MinecraftTypes.SELECTOR; } } [^] { return TokenType.BAD_CHARACTER; }
Grammar Kit文件 Minecraft.bnf 内容
{ parserClass="org.intellij.sdk.language.parser.MinecraftParser" extends="com.intellij.extapi.psi.ASTWrapperPsiElement" psiClassPrefix="Minecraft" psiImplClassSuffix="Impl" psiPackage="org.intellij.sdk.language.psi" psiImplPackage="org.intellij.sdk.language.psi.impl" elementTypeHolderClass="org.intellij.sdk.language.psi.MinecraftTypes" elementTypeClass="org.intellij.sdk.language.psi.MinecraftElementType" tokenTypeClass="org.intellij.sdk.language.psi.MinecraftTokenType" } minecraftFile ::= item* private item ::= (COMMAND|ARGUMENT|SELECTOR|COMMENT)
高亮逻辑处理文件 MinecraftSyntaxHighlighter.java 内容
package org.intellij.sdk.language; import com.intellij.lexer.Lexer; 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.TokenType; import com.intellij.psi.tree.IElementType; import org.intellij.sdk.language.psi.MinecraftTypes; import org.jetbrains.annotations.NotNull; import static com.intellij.openapi.editor.colors.TextAttributesKey.createTextAttributesKey; /** * @author Soni */ public class MinecraftSyntaxHighlighter extends SyntaxHighlighterBase { public static final TextAttributesKey COMMAND = createTextAttributesKey("MINECRAFT_COMMAND", DefaultLanguageHighlighterColors.KEYWORD); public static final TextAttributesKey ARGUMENT = createTextAttributesKey("MINECRAFT_ARGUMENT", DefaultLanguageHighlighterColors.INSTANCE_METHOD); public static final TextAttributesKey SELECTOR = createTextAttributesKey("MINECRAFT_SELECTOR", DefaultLanguageHighlighterColors.INSTANCE_FIELD); public static final TextAttributesKey COMMENT = createTextAttributesKey("MINECRAFT_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT); public static final TextAttributesKey BAD_CHARACTER = createTextAttributesKey("MINECRAFT_BAD_CHARACTER", HighlighterColors.BAD_CHARACTER); private static final TextAttributesKey[] COMMAND_KEYS = new TextAttributesKey[]{COMMAND}; private static final TextAttributesKey[] ARGUMENT_KEYS = new TextAttributesKey[]{ARGUMENT}; private static final TextAttributesKey[] SELECTOR_KEYS = new TextAttributesKey[]{SELECTOR}; private static final TextAttributesKey[] COMMENT_KEYS = new TextAttributesKey[]{COMMENT}; private static final TextAttributesKey[] BAD_CHAR_KEYS = new TextAttributesKey[]{BAD_CHARACTER}; private static final TextAttributesKey[] EMPTY_KEYS = new TextAttributesKey[0]; @NotNull @Override public Lexer getHighlightingLexer() { return new MinecraftLexerAdapter(); } @NotNull @Override public TextAttributesKey[] getTokenHighlights(IElementType tokenType) { if (tokenType.equals(MinecraftTypes.COMMAND)) return COMMAND_KEYS; else if (tokenType.equals(MinecraftTypes.ARGUMENT)) return ARGUMENT_KEYS; else if (tokenType.equals(MinecraftTypes.SELECTOR)) return SELECTOR_KEYS; else if (tokenType.equals(MinecraftTypes.COMMENT)) return COMMENT_KEYS; else if (tokenType.equals(TokenType.BAD_CHARACTER)) return BAD_CHAR_KEYS; else return EMPTY_KEYS; } }
该问题仅影响实际高亮效果,使用PsiViewer插件可以确认编写代码时PSI元素会正常更新。
如果需要补充更多代码或者进一步说明,请告知。
这个问题已经困扰我很久了,提前感谢各位的帮助。
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

