diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/index/SingleJavaFileRootsIndex.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/index/SingleJavaFileRootsIndex.kt index 0548d3a8a02..6798d1e6d27 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/index/SingleJavaFileRootsIndex.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/index/SingleJavaFileRootsIndex.kt @@ -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) { * 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) { 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 { var packageFqName = FqName.ROOT @@ -98,6 +105,7 @@ class SingleJavaFileRootsIndex(private val roots: List) { advance() } if (end()) break + advance() while (!end() && !at(ElementType.IDENTIFIER)) { advance() } diff --git a/compiler/testData/cli/jvm/Record.java b/compiler/testData/cli/jvm/Record.java new file mode 100644 index 00000000000..0bd18cdbb6a --- /dev/null +++ b/compiler/testData/cli/jvm/Record.java @@ -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) {} diff --git a/compiler/testData/cli/jvm/recordAsSingleFileRoot.args b/compiler/testData/cli/jvm/recordAsSingleFileRoot.args new file mode 100644 index 00000000000..23bc711567c --- /dev/null +++ b/compiler/testData/cli/jvm/recordAsSingleFileRoot.args @@ -0,0 +1,4 @@ +$TESTDATA_DIR$/Record.java +$TESTDATA_DIR$/recordAsSingleFileRoot.kt +-d +$TEMP_DIR$ diff --git a/compiler/testData/cli/jvm/recordAsSingleFileRoot.kt b/compiler/testData/cli/jvm/recordAsSingleFileRoot.kt new file mode 100644 index 00000000000..7ab35489cca --- /dev/null +++ b/compiler/testData/cli/jvm/recordAsSingleFileRoot.kt @@ -0,0 +1,5 @@ +// This should compile. +fun create(): Record = Record("OK") + +// This should be an error. +fun error(): Unresolved? = null diff --git a/compiler/testData/cli/jvm/recordAsSingleFileRoot.out b/compiler/testData/cli/jvm/recordAsSingleFileRoot.out new file mode 100644 index 00000000000..d024c3b914e --- /dev/null +++ b/compiler/testData/cli/jvm/recordAsSingleFileRoot.out @@ -0,0 +1,4 @@ +compiler/testData/cli/jvm/recordAsSingleFileRoot.kt:5:14: error: unresolved reference: Unresolved +fun error(): Unresolved? = null + ^ +COMPILATION_ERROR diff --git a/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java index 4e39966058b..293a2255925 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java @@ -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");