[java-rd] IDEA-322563 Improve editing experience in Remote Dev for Java

- lexer, parser, IElementType for frontend

GitOrigin-RevId: 8842d018eab3ca17749660520820174d4f792437
This commit is contained in:
Mikhail Pyltsin
2023-09-11 16:43:27 +02:00
committed by intellij-monorepo-bot
parent d247cc9ab7
commit e23e60a0eb
126 changed files with 10331 additions and 6689 deletions

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="kotlin-language" name="Kotlin">
<configuration version="5" platform="JVM 17" allPlatforms="JVM [17]" useProjectSettings="false">
<compilerSettings>
<option name="additionalArguments" value="-Xjvm-default=all -opt-in=com.intellij.openapi.util.IntellijInternalApi" />
</compilerSettings>
<compilerArguments>
<stringArguments>
<stringArg name="jvmTarget" arg="17" />
<stringArg name="apiVersion" arg="1.8" />
<stringArg name="languageVersion" arg="1.8" />
</stringArguments>
</compilerArguments>
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/resource" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="intellij.java.frontback.psi" exported="" />
<orderEntry type="module" module-name="intellij.java.frontback.psi.impl" exported="" />
<orderEntry type="module" module-name="intellij.platform.core.impl" exported="" />
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
<orderEntry type="module" module-name="intellij.platform.core.ui" />
<orderEntry type="module" module-name="intellij.xml.frontback" exported="" />
<orderEntry type="module" module-name="intellij.platform.core" />
</component>
</module>

View File

@@ -0,0 +1,6 @@
<idea-plugin package="com.intellij.codeInsight.definition">
<module value="com.intellij.java.frontback.impl" />
<extensionPoints>
<extensionPoint qualifiedName="com.intellij.java.definitions" interface="com.intellij.codeInsight.definition.AbstractBasicJavaDefinitionService" dynamic="true"/>
</extensionPoints>
</idea-plugin>

View File

@@ -0,0 +1,13 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij;
import com.intellij.lang.xml.XmlTokenElementMarkTypes;
import com.intellij.psi.impl.source.BasicJavaTokenSet;
import com.intellij.psi.tree.TokenSet;
public interface BaseJavaJspElementType {
BasicJavaTokenSet WHITE_SPACE_BIT_SET = BasicJavaTokenSet.orSet(
BasicJavaTokenSet.create(TokenSet.WHITE_SPACE),
BasicJavaTokenSet.create(XmlTokenElementMarkTypes.XML_WHITE_SPACE_MARK));
}

View File

@@ -0,0 +1,30 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.definition;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@ApiStatus.Experimental
public abstract class AbstractBasicJavaDefinitionService {
public static final ExtensionPointName<AbstractBasicJavaDefinitionService>
EP_NAME = ExtensionPointName.create("com.intellij.java.definitions");
private static class AbstractBasicJavaDefinitionServiceHelper {
private static final AbstractBasicJavaDefinitionService INSTANCE = EP_NAME.getExtensionList().get(0);
}
public static AbstractBasicJavaDefinitionService getJavaDefinitionService() {
return AbstractBasicJavaDefinitionServiceHelper.INSTANCE;
}
@NotNull
public abstract LanguageLevel getLanguageLevel(@NotNull PsiElement psiElement);
@NotNull
public abstract LanguageLevel getLanguageLevel(@NotNull Project project);
}

View File

@@ -0,0 +1,94 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.highlighter;
import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaDocTokenType;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.StringEscapesTokenTypes;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.ParentProviderElementType;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import static com.intellij.psi.impl.source.BasicElementTypes.*;
public abstract class AbstractBasicJavaFileHighlighter extends SyntaxHighlighterBase {
private final Map<IElementType, TextAttributesKey> ourMap1;
private final Map<IElementType, TextAttributesKey> ourMap2;
protected final LanguageLevel myLanguageLevel;
public AbstractBasicJavaFileHighlighter(@NotNull LanguageLevel languageLevel) {
myLanguageLevel = languageLevel;
ourMap1 = new HashMap<>();
ourMap2 = new HashMap<>();
fillMap(ourMap1, KEYWORD_BIT_SET.toTokenSet(), JavaHighlightingColors.KEYWORD);
fillMap(ourMap1, LITERAL_BIT_SET.toTokenSet(), JavaHighlightingColors.KEYWORD);
fillMap(ourMap1, OPERATION_BIT_SET.toTokenSet(), JavaHighlightingColors.OPERATION_SIGN);
for (IElementType type : JavaDocTokenType.ALL_JAVADOC_TOKENS.getTypes()) {
ourMap1.put(type, JavaHighlightingColors.DOC_COMMENT);
}
ourMap1.put(JavaTokenType.INTEGER_LITERAL, JavaHighlightingColors.NUMBER);
ourMap1.put(JavaTokenType.LONG_LITERAL, JavaHighlightingColors.NUMBER);
ourMap1.put(JavaTokenType.FLOAT_LITERAL, JavaHighlightingColors.NUMBER);
ourMap1.put(JavaTokenType.DOUBLE_LITERAL, JavaHighlightingColors.NUMBER);
ourMap1.put(JavaTokenType.STRING_LITERAL, JavaHighlightingColors.STRING);
ourMap1.put(JavaTokenType.TEXT_BLOCK_LITERAL, JavaHighlightingColors.STRING);
ourMap1.put(JavaTokenType.STRING_TEMPLATE_BEGIN, JavaHighlightingColors.STRING);
ourMap1.put(JavaTokenType.STRING_TEMPLATE_MID, JavaHighlightingColors.STRING);
ourMap1.put(JavaTokenType.STRING_TEMPLATE_END, JavaHighlightingColors.STRING);
ourMap1.put(JavaTokenType.TEXT_BLOCK_TEMPLATE_BEGIN, JavaHighlightingColors.STRING);
ourMap1.put(JavaTokenType.TEXT_BLOCK_TEMPLATE_MID, JavaHighlightingColors.STRING);
ourMap1.put(JavaTokenType.TEXT_BLOCK_TEMPLATE_END, JavaHighlightingColors.STRING);
ourMap1.put(StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN, JavaHighlightingColors.VALID_STRING_ESCAPE);
ourMap1.put(StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN, JavaHighlightingColors.INVALID_STRING_ESCAPE);
ourMap1.put(StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN, JavaHighlightingColors.INVALID_STRING_ESCAPE);
ourMap1.put(JavaTokenType.CHARACTER_LITERAL, JavaHighlightingColors.STRING);
ourMap1.put(JavaTokenType.LPARENTH, JavaHighlightingColors.PARENTHESES);
ourMap1.put(JavaTokenType.RPARENTH, JavaHighlightingColors.PARENTHESES);
ourMap1.put(JavaTokenType.LBRACE, JavaHighlightingColors.BRACES);
ourMap1.put(JavaTokenType.RBRACE, JavaHighlightingColors.BRACES);
ourMap1.put(JavaTokenType.LBRACKET, JavaHighlightingColors.BRACKETS);
ourMap1.put(JavaTokenType.RBRACKET, JavaHighlightingColors.BRACKETS);
ourMap1.put(JavaTokenType.COMMA, JavaHighlightingColors.COMMA);
ourMap1.put(JavaTokenType.DOT, JavaHighlightingColors.DOT);
ourMap1.put(JavaTokenType.SEMICOLON, JavaHighlightingColors.JAVA_SEMICOLON);
ourMap1.put(JavaTokenType.C_STYLE_COMMENT, JavaHighlightingColors.JAVA_BLOCK_COMMENT);
ourMap1.put(DOC_COMMENT, JavaHighlightingColors.DOC_COMMENT);
ourMap1.put(JavaTokenType.END_OF_LINE_COMMENT, JavaHighlightingColors.LINE_COMMENT);
ourMap1.put(TokenType.BAD_CHARACTER, HighlighterColors.BAD_CHARACTER);
ourMap1.put(JavaDocTokenType.DOC_TAG_NAME, JavaHighlightingColors.DOC_COMMENT);
ourMap2.put(JavaDocTokenType.DOC_TAG_NAME, JavaHighlightingColors.DOC_COMMENT_TAG);
//noinspection AbstractMethodCallInConstructor
initAdditional(ourMap1, ourMap2);
}
protected abstract void initAdditional(@NotNull Map<IElementType, TextAttributesKey> map1,
@NotNull Map<IElementType, TextAttributesKey> map2);
@Override
public TextAttributesKey @NotNull [] getTokenHighlights(IElementType tokenType) {
while (tokenType instanceof ParentProviderElementType parentProviderElementType) {
if (parentProviderElementType.getParents().size() == 1) {
tokenType = parentProviderElementType.getParents().iterator().next();
}
}
return pack(ourMap1.get(tokenType), ourMap2.get(tokenType));
}
}

View File

@@ -0,0 +1,45 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.lexer;
import com.intellij.lang.java.lexer.BasicJavaLexer;
import com.intellij.lang.java.lexer.JavaDocLexer;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractBasicJavaHighlightingLexer extends LayeredLexer {
public AbstractBasicJavaHighlightingLexer(@NotNull LanguageLevel languageLevel,
@NotNull BasicJavaLexer javaLexer) {
super(javaLexer);
registerSelfStoppingLayer(new JavaStringLiteralLexer('\"', JavaTokenType.STRING_LITERAL, false, "s{"),
new IElementType[]{JavaTokenType.STRING_LITERAL}, IElementType.EMPTY_ARRAY);
registerSelfStoppingLayer(new JavaStringLiteralLexer('\'', JavaTokenType.STRING_LITERAL, false, "s"),
new IElementType[]{JavaTokenType.CHARACTER_LITERAL}, IElementType.EMPTY_ARRAY);
registerSelfStoppingLayer(new JavaStringLiteralLexer(StringLiteralLexer.NO_QUOTE_CHAR, JavaTokenType.TEXT_BLOCK_LITERAL, true, "s{"),
new IElementType[]{JavaTokenType.TEXT_BLOCK_LITERAL}, IElementType.EMPTY_ARRAY);
registerSelfStoppingLayer(new JavaStringLiteralLexer(StringLiteralLexer.NO_QUOTE_CHAR, JavaTokenType.TEXT_BLOCK_TEMPLATE_BEGIN, true, "s"),
new IElementType[]{JavaTokenType.TEXT_BLOCK_TEMPLATE_BEGIN}, IElementType.EMPTY_ARRAY);
registerSelfStoppingLayer(new JavaStringLiteralLexer(StringLiteralLexer.NO_QUOTE_CHAR, JavaTokenType.TEXT_BLOCK_TEMPLATE_MID, true, "s"),
new IElementType[]{JavaTokenType.TEXT_BLOCK_TEMPLATE_MID}, IElementType.EMPTY_ARRAY);
registerSelfStoppingLayer(new JavaStringLiteralLexer(StringLiteralLexer.NO_QUOTE_CHAR, JavaTokenType.TEXT_BLOCK_TEMPLATE_END, true, "s"),
new IElementType[]{JavaTokenType.TEXT_BLOCK_TEMPLATE_END}, IElementType.EMPTY_ARRAY);
registerSelfStoppingLayer(new JavaStringLiteralLexer(StringLiteralLexer.NO_QUOTE_CHAR, JavaTokenType.STRING_TEMPLATE_BEGIN, true, "s"),
new IElementType[]{JavaTokenType.STRING_TEMPLATE_BEGIN}, IElementType.EMPTY_ARRAY);
registerSelfStoppingLayer(new JavaStringLiteralLexer(StringLiteralLexer.NO_QUOTE_CHAR, JavaTokenType.STRING_TEMPLATE_MID, true, "s"),
new IElementType[]{JavaTokenType.STRING_TEMPLATE_MID}, IElementType.EMPTY_ARRAY);
registerSelfStoppingLayer(new JavaStringLiteralLexer(StringLiteralLexer.NO_QUOTE_CHAR, JavaTokenType.STRING_TEMPLATE_END, true, "s"),
new IElementType[]{JavaTokenType.STRING_TEMPLATE_END}, IElementType.EMPTY_ARRAY);
LayeredLexer docLexer = new LayeredLexer(new JavaDocLexer(languageLevel));
//noinspection AbstractMethodCallInConstructor
registerDocLayers(docLexer);
}
protected abstract void registerDocLayers(@NotNull LayeredLexer docLexer);
}

View File

@@ -0,0 +1,84 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.lexer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.StringEscapesTokenTypes;
import com.intellij.psi.impl.source.BasicElementTypes;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
class JavaStringLiteralLexer extends StringLiteralLexer {
JavaStringLiteralLexer(char quoteChar, IElementType originalLiteralToken) {
super(quoteChar, originalLiteralToken);
}
JavaStringLiteralLexer(char quoteChar,
IElementType originalLiteralToken,
boolean canEscapeEolOrFramingSpaces,
String additionalValidEscapes) {
super(quoteChar, originalLiteralToken, canEscapeEolOrFramingSpaces, additionalValidEscapes);
}
@Override
public IElementType getTokenType() {
IElementType tokenType = super.getTokenType();
if (tokenType == StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN) {
char c = myBuffer.charAt(myStart + 1);
if (c == '{' && BasicElementTypes.STRING_TEMPLATE_FRAGMENTS.contains(myOriginalLiteralToken)) {
// don't highlight \{ in template fragment as bad escape
return myOriginalLiteralToken;
}
}
return tokenType;
}
@Override
protected @NotNull IElementType getUnicodeEscapeSequenceType() {
int start = myStart + 2;
while (start < myEnd && myBuffer.charAt(start) == 'u') start++;
if (start + 3 >= myEnd) return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN;
if (!StringUtil.isHexDigit(myBuffer.charAt(start)) ||
!StringUtil.isHexDigit(myBuffer.charAt(start + 1)) ||
!StringUtil.isHexDigit(myBuffer.charAt(start + 2)) ||
!StringUtil.isHexDigit(myBuffer.charAt(start + 3))) {
return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN;
}
return StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN;
}
@Override
protected int locateUnicodeEscapeSequence(int start, int i) {
do {
i++;
}
while (i < myBufferEnd && myBuffer.charAt(i) == 'u');
int end = parseUnicodeDigits(i);
if (end != i + 4) return end;
int code = Integer.parseInt(myBuffer.subSequence(i, end).toString(), 16);
i = end;
// if escape sequence is not translated to backspace then continue from the next symbol
if (code != '\\' || i >= myBufferEnd) return i;
char c = myBuffer.charAt(i);
if (StringUtil.isOctalDigit(c)) {
if (i + 2 < myBufferEnd && StringUtil.isOctalDigit(myBuffer.charAt(i + 1)) && StringUtil.isOctalDigit(myBuffer.charAt(i + 1))) {
return i + 3;
}
}
else if (c == '\\' && i + 1 < myBufferEnd && myBuffer.charAt(i + 1) == 'u') {
i += 2;
while (i < myBufferEnd && myBuffer.charAt(i) == 'u') i++;
return parseUnicodeDigits(i);
}
return i + 1;
}
private int parseUnicodeDigits(int i) {
int end = i + 4;
for (; i < end; i++) {
if (i == myBufferEnd) return i;
if (!StringUtil.isHexDigit(myBuffer.charAt(i))) return i;
}
return end;
}
}