mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Lexer for sealed classes: IDEA-223111
GitOrigin-RevId: 03526b93d73bd1a96d0db58b008163db9c573fb2
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6a3633295a
commit
ea992d5d4c
@@ -142,4 +142,8 @@ public interface JavaTokenType extends TokenType {
|
||||
IElementType VAR_KEYWORD = new IJavaElementType("VAR");
|
||||
IElementType YIELD_KEYWORD = new IJavaElementType("YIELD");
|
||||
IElementType RECORD_KEYWORD = new IJavaElementType("RECORD");
|
||||
|
||||
IElementType SEALED_KEYWORD = new IJavaElementType("SEALED");
|
||||
IElementType NON_SEALED_KEYWORD = new IKeywordElementType("NON_SEALED");
|
||||
IElementType PERMITS_KEYWORD = new IJavaElementType("PERMITS");
|
||||
}
|
||||
@@ -75,4 +75,8 @@ public interface PsiKeyword extends PsiJavaToken {
|
||||
String YIELD = "yield";
|
||||
|
||||
String RECORD = "record";
|
||||
|
||||
String SEALED = "sealed";
|
||||
String PERMITS = "permits";
|
||||
String NON_SEALED = "non-sealed";
|
||||
}
|
||||
@@ -25,12 +25,17 @@ public class JavaLexer extends LexerBase {
|
||||
ABSTRACT, BOOLEAN, BREAK, BYTE, CASE, CATCH, CHAR, CLASS, CONST, CONTINUE, DEFAULT, DO, DOUBLE, ELSE, EXTENDS, FINAL, FINALLY,
|
||||
FLOAT, FOR, GOTO, IF, IMPLEMENTS, IMPORT, INSTANCEOF, INT, INTERFACE, LONG, NATIVE, NEW, PACKAGE, PRIVATE, PROTECTED, PUBLIC,
|
||||
RETURN, SHORT, STATIC, STRICTFP, SUPER, SWITCH, SYNCHRONIZED, THIS, THROW, THROWS, TRANSIENT, TRY, VOID, VOLATILE, WHILE,
|
||||
TRUE, FALSE, NULL);
|
||||
TRUE, FALSE, NULL, NON_SEALED);
|
||||
|
||||
private static final Set<CharSequence> JAVA9_KEYWORDS =
|
||||
new THashSet<>(Arrays.asList(OPEN, MODULE, REQUIRES, EXPORTS, OPENS, USES, PROVIDES, TRANSITIVE, TO, WITH),
|
||||
CharSequenceHashingStrategy.CASE_SENSITIVE);
|
||||
|
||||
// Minus is a single token that may separate identifiers that can form "non-sealed" keyword
|
||||
// For incremental lexing it is important that at "-" lexer is not in the initial state so we will lex one more token
|
||||
private static final int INITIAL_STATE = 0;
|
||||
private static final int MAYBE_NON_SEALED_STATE = -1;
|
||||
|
||||
public static boolean isKeyword(String id, @NotNull LanguageLevel level) {
|
||||
return KEYWORDS.contains(id) ||
|
||||
level.isAtLeast(LanguageLevel.JDK_1_4) && ASSERT.equals(id) ||
|
||||
@@ -41,19 +46,24 @@ public class JavaLexer extends LexerBase {
|
||||
return id != null &&
|
||||
(level.isAtLeast(LanguageLevel.JDK_1_9) && JAVA9_KEYWORDS.contains(id) ||
|
||||
level.isAtLeast(LanguageLevel.JDK_10) && VAR.contentEquals(id) ||
|
||||
level.isAtLeast(LanguageLevel.JDK_14_PREVIEW) && RECORD.contentEquals(id) ||
|
||||
level.isAtLeast(LanguageLevel.JDK_14) && YIELD.contentEquals(id) ||
|
||||
level.isAtLeast(LanguageLevel.JDK_14_PREVIEW) && RECORD.contentEquals(id));
|
||||
(level.isAtLeast(LanguageLevel.JDK_15_PREVIEW) && (SEALED.contentEquals(id) || PERMITS.contentEquals(id)))
|
||||
);
|
||||
}
|
||||
|
||||
private final _JavaLexer myFlexLexer;
|
||||
private final LanguageLevel myLevel;
|
||||
private CharSequence myBuffer;
|
||||
private char @Nullable [] myBufferArray;
|
||||
private int myBufferIndex;
|
||||
private int myBufferEndOffset;
|
||||
private int myTokenEndOffset; // positioned after the last symbol of the current token
|
||||
private IElementType myTokenType;
|
||||
private int myState = INITIAL_STATE;
|
||||
|
||||
public JavaLexer(@NotNull LanguageLevel level) {
|
||||
myLevel = level;
|
||||
myFlexLexer = new _JavaLexer(level);
|
||||
}
|
||||
|
||||
@@ -70,7 +80,7 @@ public class JavaLexer extends LexerBase {
|
||||
|
||||
@Override
|
||||
public int getState() {
|
||||
return 0;
|
||||
return myState;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -106,6 +116,7 @@ public class JavaLexer extends LexerBase {
|
||||
|
||||
myBufferIndex = myTokenEndOffset;
|
||||
|
||||
boolean wasMinus = false;
|
||||
char c = charAt(myBufferIndex);
|
||||
switch (c) {
|
||||
case ' ':
|
||||
@@ -162,10 +173,36 @@ public class JavaLexer extends LexerBase {
|
||||
myTokenEndOffset = getClosingQuote(myBufferIndex + 1, c);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (myLevel.isAtLeast(LanguageLevel.JDK_15_PREVIEW) &&
|
||||
myBufferIndex + 9 < myBufferEndOffset &&
|
||||
charAt(myBufferIndex + 1) == 'o' &&
|
||||
charAt(myBufferIndex + 2) == 'n' &&
|
||||
charAt(myBufferIndex + 3) == '-' &&
|
||||
charAt(myBufferIndex + 4) == 's' &&
|
||||
charAt(myBufferIndex + 5) == 'e' &&
|
||||
charAt(myBufferIndex + 6) == 'a' &&
|
||||
charAt(myBufferIndex + 7) == 'l' &&
|
||||
charAt(myBufferIndex + 8) == 'e' &&
|
||||
charAt(myBufferIndex + 9) == 'd') {
|
||||
myTokenType = JavaTokenType.NON_SEALED_KEYWORD;
|
||||
myTokenEndOffset = myBufferIndex + 10;
|
||||
}
|
||||
else {
|
||||
flexLocateToken();
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
wasMinus = true;
|
||||
// fallthrough
|
||||
default:
|
||||
flexLocateToken();
|
||||
}
|
||||
if (wasMinus) {
|
||||
myState = MAYBE_NON_SEALED_STATE;
|
||||
} else {
|
||||
myState = INITIAL_STATE;
|
||||
}
|
||||
|
||||
if (myTokenEndOffset > myBufferEndOffset) {
|
||||
myTokenEndOffset = myBufferEndOffset;
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.JavaDocTokenType;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.testFramework.LightJavaCodeInsightTestCase;
|
||||
@@ -24,6 +25,11 @@ public class JavaHighlighterTest extends LightJavaCodeInsightTestCase {
|
||||
private Document myDocument;
|
||||
private final ArrayList<Editor> myEditorsToRelease = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return LanguageLevel.JDK_15_PREVIEW;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
try {
|
||||
@@ -158,6 +164,23 @@ public class JavaHighlighterTest extends LightJavaCodeInsightTestCase {
|
||||
CheckHighlighterConsistency.performCheck(editor);
|
||||
}
|
||||
|
||||
public void testNonSealedEditing() {
|
||||
Editor editor = initDocument("non-sealed class A {\n" +
|
||||
" \n" +
|
||||
"} ");
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
|
||||
int idx = myDocument.getText().lastIndexOf(" class");
|
||||
myDocument.deleteString(idx - 1, idx);
|
||||
});
|
||||
CheckHighlighterConsistency.performCheck(editor);
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
|
||||
int idx = myDocument.getText().lastIndexOf(" class");
|
||||
myDocument.insertString(idx, "d");
|
||||
});
|
||||
CheckHighlighterConsistency.performCheck(editor);
|
||||
}
|
||||
|
||||
private Editor initDocument(String text) {
|
||||
EditorFactory editorFactory = EditorFactory.getInstance();
|
||||
myDocument = editorFactory.createDocument(text);
|
||||
@@ -165,7 +188,7 @@ public class JavaHighlighterTest extends LightJavaCodeInsightTestCase {
|
||||
|
||||
myHighlighter = HighlighterFactory
|
||||
.createHighlighter(JavaFileType.INSTANCE, EditorColorsManager.getInstance().getGlobalScheme(), getProject());
|
||||
((EditorEx) editor).setHighlighter(myHighlighter);
|
||||
((EditorEx)editor).setHighlighter(myHighlighter);
|
||||
|
||||
myEditorsToRelease.add(editor);
|
||||
return editor;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2000-2019 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.java.lexer;
|
||||
|
||||
import com.intellij.lang.java.JavaParserDefinition;
|
||||
import com.intellij.lexer.Lexer;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.LexerTestCase;
|
||||
|
||||
public class Java15LexerTest extends LexerTestCase {
|
||||
public void testNonSealed() {
|
||||
doTest("non-sealed", "NON_SEALED ('non-sealed')");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Lexer createLexer() {
|
||||
return JavaParserDefinition.createLexer(LanguageLevel.JDK_15_PREVIEW);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDirPath() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user