问题描述
免责声明:这个问题主要针对至少具有 IntelliJ 平台插件创建基础知识的人。
为了让自己更轻松地制作插件,我决定创建一个突出显示 .mcfunction
代码的插件。 (我的世界命令)
只要关键字少于 5 个符号,我的代码就可以很好地工作。但是,长度超过 4 个符号的关键字在重新加载之前不会突出显示。
让我演示一下:
Image: Code after reloading file
这里除了重新加载文件之外没有做任何其他事情。这只发生在长度超过 4 个符号的关键字上。在以下示例中,function
和 test
共享相同的语法高亮代码:
Image: Commenting and uncommenting also fixes the highlighting
我的代码
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; }
{
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 绝望地举起它的比喻手并决定停止尝试解析有这么多错误的行,我也不会感到惊讶。 (四是一个很常见的阈值。)
我建议尝试对词法分析器(和解析器,如果有的话)没有错误地接受的内容更加慷慨。除了匹配您感兴趣的特定关键字之外,还可以匹配任何有效的标识符或数字。匹配运算符字符和括号。以及在您语法突出显示的语言中传递给字符串文字的任何内容。这不是很多工作,而且成功的可能性更大(至少在我头脑中的理论世界中)。