CLI: fix resolution of Java records as single file roots

#KT-46764 Fixed
This commit is contained in:
Alexander Udalov
2021-05-31 21:52:09 +02:00
parent e295849733
commit 4b7fa44e80
6 changed files with 34 additions and 2 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.cli.jvm.index
import com.intellij.lang.java.lexer.JavaLexer import com.intellij.lang.java.lexer.JavaLexer
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.pom.java.LanguageLevel import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.PsiKeyword
import com.intellij.psi.impl.source.tree.ElementType import com.intellij.psi.impl.source.tree.ElementType
import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -53,7 +54,7 @@ class SingleJavaFileRootsIndex(private val roots: List<JavaRoot>) {
* Given a .java file, [readClassIds] uses lexer to determine which classes are declared in that file * Given a .java file, [readClassIds] uses lexer to determine which classes are declared in that file
*/ */
private class JavaSourceClassIdReader(file: VirtualFile) { private class JavaSourceClassIdReader(file: VirtualFile) {
private val lexer = JavaLexer(LanguageLevel.JDK_1_9).apply { private val lexer = JavaLexer(LanguageLevel.HIGHEST).apply {
start(String(file.contentsToByteArray())) start(String(file.contentsToByteArray()))
} }
private var braceBalance = 0 private var braceBalance = 0
@@ -73,7 +74,13 @@ class SingleJavaFileRootsIndex(private val roots: List<JavaRoot>) {
private fun tokenText(): String = lexer.tokenText private fun tokenText(): String = lexer.tokenText
private fun atClass(): Boolean = private fun atClass(): Boolean =
braceBalance == 0 && lexer.tokenType in CLASS_KEYWORDS braceBalance == 0 && (lexer.tokenType in CLASS_KEYWORDS || atRecord())
private fun atRecord(): Boolean {
// Note that the soft keyword "record" is lexed as IDENTIFIER instead of RECORD_KEYWORD.
// This is kind of a sloppy way to parse a soft keyword, but we only do it at the top level, where it seems to work fine.
return at(ElementType.IDENTIFIER) && tokenText() == PsiKeyword.RECORD
}
fun readClassIds(): List<ClassId> { fun readClassIds(): List<ClassId> {
var packageFqName = FqName.ROOT var packageFqName = FqName.ROOT
@@ -98,6 +105,7 @@ class SingleJavaFileRootsIndex(private val roots: List<JavaRoot>) {
advance() advance()
} }
if (end()) break if (end()) break
advance()
while (!end() && !at(ElementType.IDENTIFIER)) { while (!end() && !at(ElementType.IDENTIFIER)) {
advance() advance()
} }
+6
View File
@@ -0,0 +1,6 @@
// This import checks that the compiler won't parse the "record" word as a soft keyword
// and load the non-existing class named "Unresolved" from this Java source.
import record.Unresolved;
// This class should be resolved correctly.
public record Record(String string) {}
+4
View File
@@ -0,0 +1,4 @@
$TESTDATA_DIR$/Record.java
$TESTDATA_DIR$/recordAsSingleFileRoot.kt
-d
$TEMP_DIR$
+5
View File
@@ -0,0 +1,5 @@
// This should compile.
fun create(): Record = Record("OK")
// This should be an error.
fun error(): Unresolved? = null
+4
View File
@@ -0,0 +1,4 @@
compiler/testData/cli/jvm/recordAsSingleFileRoot.kt:5:14: error: unresolved reference: Unresolved
fun error(): Unresolved? = null
^
COMPILATION_ERROR
@@ -711,6 +711,11 @@ public class CliTestGenerated extends AbstractCliTest {
runTest("compiler/testData/cli/jvm/progressiveModeOn.args"); runTest("compiler/testData/cli/jvm/progressiveModeOn.args");
} }
@TestMetadata("recordAsSingleFileRoot.args")
public void testRecordAsSingleFileRoot() throws Exception {
runTest("compiler/testData/cli/jvm/recordAsSingleFileRoot.args");
}
@TestMetadata("resultInReturnTypeSupportedByDefault15.args") @TestMetadata("resultInReturnTypeSupportedByDefault15.args")
public void testResultInReturnTypeSupportedByDefault15() throws Exception { public void testResultInReturnTypeSupportedByDefault15() throws Exception {
runTest("compiler/testData/cli/jvm/resultInReturnTypeSupportedByDefault15.args"); runTest("compiler/testData/cli/jvm/resultInReturnTypeSupportedByDefault15.args");