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.openapi.vfs.VirtualFile
import com.intellij.pom.java.LanguageLevel
import com.intellij.psi.PsiKeyword
import com.intellij.psi.impl.source.tree.ElementType
import com.intellij.psi.tree.IElementType
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
*/
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()))
}
private var braceBalance = 0
@@ -73,7 +74,13 @@ class SingleJavaFileRootsIndex(private val roots: List<JavaRoot>) {
private fun tokenText(): String = lexer.tokenText
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> {
var packageFqName = FqName.ROOT
@@ -98,6 +105,7 @@ class SingleJavaFileRootsIndex(private val roots: List<JavaRoot>) {
advance()
}
if (end()) break
advance()
while (!end() && !at(ElementType.IDENTIFIER)) {
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");
}
@TestMetadata("recordAsSingleFileRoot.args")
public void testRecordAsSingleFileRoot() throws Exception {
runTest("compiler/testData/cli/jvm/recordAsSingleFileRoot.args");
}
@TestMetadata("resultInReturnTypeSupportedByDefault15.args")
public void testResultInReturnTypeSupportedByDefault15() throws Exception {
runTest("compiler/testData/cli/jvm/resultInReturnTypeSupportedByDefault15.args");