IntelliJ 语法高亮显示在 5 个符号后停止 我的代码

问题描述

免责声明:这个问题主要针对至少具有 IntelliJ 平台插件创建基础知识的人。

为了让自己更轻松地制作插件,我决定创建一个突出显示 .mcfunction 代码插件。 (我的世界命令)

只要关键字少于 5 个符号,我的代码就可以很好地工作。但是,长度超过 4 个符号的关键字在重新加载之前不会突出显示


让我演示一下:

Image: Code when typed in

Image: Code after reloading file

这里除了重新加载文件之外没有做任何其他事情。这只发生在长度超过 4 个符号的关键字上。在以下示例中,functiontest 共享相同的语法高亮代码

Image: Code when typed in

Image: Commenting and uncommenting also fixes the highlighting

Image: Correct highlighthing


我的代码

minecraft.flex 中,jflex 文件

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; }

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 元素在编写代码时更新。

如果您希望我在问题中包含更多代码,或者您需要澄清,请告诉我。

这让我很头疼。预先感谢您的帮助。

解决方法

我不属于这个问题的目标群体,因为我没有使用 IntelliJ 的经验,更不用说编写自定义语法荧光笔了。不过我还是看了看你的代码。

您的自定义词法分析器只能识别少数特殊标记。与其中之一不匹配的每个字符都被标记为错误。这是很多错误,如果有一点 IntelliJ 绝望地举起它的比喻手并决定停止尝试解析有这么多错误的行,我也不会感到惊讶。 (四是一个很常见的阈值。)

我建议尝试对词法分析器(和解析器,如果有的话)没有错误地接受的内容更加慷慨。除了匹配您感兴趣的特定关键字之外,还可以匹配任何有效的标识符或数字。匹配运算符字符和括号。以及在您语法突出显示的语言中传递给字符串文字的任何内容。这不是很多工作,而且成功的可能性更大(至少在我头脑中的理论世界中)。