Light classes: use JVM target from the module

Using "JVM_1_8" always resulted in incorrect mapping of Kotlin
annotation targets to Java element types.

The change in AbstractKotlinRenderLogTest is needed because while
CliTraceHolder.module is technically a descriptor leak, it was never
detected by this test accidentally, because of the depth cutoff equal to
10, which started to not be enough after the minor refactoring of
replacing `Delegates.notNull` with `lateinit`.
This commit is contained in:
Alexander Udalov
2021-01-25 18:59:38 +01:00
parent 64e97225b8
commit adfa8c788c
24 changed files with 234 additions and 92 deletions
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
import org.jetbrains.kotlin.idea.project.IdeaEnvironment
import org.jetbrains.kotlin.idea.project.ResolveElementCache
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.stubindex.KotlinOverridableInternalMembersShortNameIndex
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -69,12 +70,13 @@ import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.WrappedTypeFactory
import org.jetbrains.kotlin.utils.sure
class IDELightClassConstructionContext(
bindingContext: BindingContext, module: ModuleDescriptor,
bindingContext: BindingContext,
module: ModuleDescriptor,
languageVersionSettings: LanguageVersionSettings,
jvmTarget: JvmTarget,
val mode: Mode
) : LightClassConstructionContext(bindingContext, module, languageVersionSettings) {
) : LightClassConstructionContext(bindingContext, module, languageVersionSettings, jvmTarget) {
enum class Mode {
LIGHT,
EXACT
@@ -106,6 +108,7 @@ internal object IDELightClassContexts {
bindingContext,
resolutionFacade.moduleDescriptor,
classOrObject.languageVersionSettings,
resolutionFacade.jvmTarget,
EXACT
)
}
@@ -122,6 +125,7 @@ internal object IDELightClassContexts {
bindingContext,
resolutionFacade.moduleDescriptor,
classOrObject.languageVersionSettings,
resolutionFacade.jvmTarget,
EXACT
)
}
@@ -132,20 +136,24 @@ internal object IDELightClassContexts {
bindingContext,
resolutionFacade.moduleDescriptor,
classOrObject.languageVersionSettings,
resolutionFacade.jvmTarget,
EXACT
)
}
fun contextForFacade(files: List<KtFile>): LightClassConstructionContext {
val resolutionFacade = files.first().getResolutionFacade()
@OptIn(FrontendInternals::class)
val resolveSession = files.first().getResolutionFacade().getFrontendService(ResolveSession::class.java)
val resolveSession = resolutionFacade.getFrontendService(ResolveSession::class.java)
forceResolvePackageDeclarations(files, resolveSession)
return IDELightClassConstructionContext(
resolveSession.bindingContext,
resolveSession.moduleDescriptor,
files.first().languageVersionSettings,
resolutionFacade.jvmTarget,
EXACT
)
}
@@ -161,21 +169,26 @@ internal object IDELightClassContexts {
bindingContext,
resolutionFacade.moduleDescriptor,
script.languageVersionSettings,
resolutionFacade.jvmTarget,
EXACT
)
}
ForceResolveUtil.forceResolveAllContents(descriptor)
return IDELightClassConstructionContext(bindingContext, resolutionFacade.moduleDescriptor, script.languageVersionSettings, EXACT)
return IDELightClassConstructionContext(
bindingContext, resolutionFacade.moduleDescriptor, script.languageVersionSettings, resolutionFacade.jvmTarget,
EXACT
)
}
fun lightContextForClassOrObject(classOrObject: KtClassOrObject): LightClassConstructionContext? {
if (!isDummyResolveApplicable(classOrObject)) return null
val resolutionFacade = classOrObject.getResolutionFacade()
val resolveSession = setupAdHocResolve(
classOrObject.project,
classOrObject.getResolutionFacade().moduleDescriptor,
resolutionFacade.moduleDescriptor,
listOf(classOrObject.containingKtFile)
)
@@ -188,13 +201,15 @@ internal object IDELightClassContexts {
resolveSession.bindingContext,
resolveSession.moduleDescriptor,
classOrObject.languageVersionSettings,
resolutionFacade.jvmTarget,
LIGHT
)
}
fun lightContextForFacade(files: List<KtFile>): LightClassConstructionContext {
val representativeFile = files.first()
val resolveSession = setupAdHocResolve(representativeFile.project, representativeFile.getResolutionFacade().moduleDescriptor, files)
val resolutionFacade = representativeFile.getResolutionFacade()
val resolveSession = setupAdHocResolve(representativeFile.project, resolutionFacade.moduleDescriptor, files)
forceResolvePackageDeclarations(files, resolveSession)
@@ -202,10 +217,15 @@ internal object IDELightClassContexts {
resolveSession.bindingContext,
resolveSession.moduleDescriptor,
files.first().languageVersionSettings,
resolutionFacade.jvmTarget,
LIGHT
)
}
@OptIn(FrontendInternals::class)
private val ResolutionFacade.jvmTarget: JvmTarget
get() = getFrontendService(JvmTarget::class.java)
private fun isDummyResolveApplicable(classOrObject: KtClassOrObject): Boolean {
if (classOrObject.hasModifier(KtTokens.INLINE_KEYWORD)) return false
@@ -447,4 +467,3 @@ internal object IDELightClassContexts {
}
}
}
@@ -31,9 +31,12 @@ import org.jetbrains.kotlin.idea.FrontendInternals
import org.jetbrains.kotlin.idea.caches.lightClasses.IDELightClassContexts
import org.jetbrains.kotlin.idea.caches.lightClasses.LazyLightClassDataHolder
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.project.platform
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.stubindex.KotlinTypeAliasShortNameIndex
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.jvm.JdkPlatform
import org.jetbrains.kotlin.platform.subplatformsOfType
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
@@ -82,7 +85,7 @@ class IDELightClassGenerationSupport(project: Project) : LightClassGenerationSup
BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
moduleName, languageVersionSettings,
useOldInlineClassesManglingScheme = false,
jvmTarget = JvmTarget.JVM_1_8,
jvmTarget = module?.platform?.subplatformsOfType<JdkPlatform>()?.firstOrNull()?.targetVersion ?: JvmTarget.DEFAULT,
typePreprocessor = KotlinType::cleanFromAnonymousTypes,
namePreprocessor = ::tryGetPredefinedName
)
@@ -29,6 +29,11 @@ public class FirClassLoadingTestGenerated extends AbstractFirClassLoadingTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/asJava/ultraLightClasses"), Pattern.compile("^(.+)\\.(kt|kts)$"), null, true);
}
@TestMetadata("annotationTargets_1_6.kt")
public void testAnnotationTargets_1_6() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/annotationTargets_1_6.kt");
}
@TestMetadata("annotationWithSetParamPropertyModifier.kt")
public void testAnnotationWithSetParamPropertyModifier() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/annotationWithSetParamPropertyModifier.kt");
@@ -149,6 +149,11 @@ public class FirLightClassTestGenerated extends AbstractFirLightClassTest {
runTest("compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass.kt");
}
@TestMetadata("SpecialAnnotationsOnAnnotationClass_1_6.kt")
public void testSpecialAnnotationsOnAnnotationClass_1_6() throws Exception {
runTest("compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass_1_6.kt");
}
@TestMetadata("StubOrderForOverloads.kt")
public void testStubOrderForOverloads() throws Exception {
runTest("compiler/testData/asJava/lightClasses/StubOrderForOverloads.kt");
@@ -29,6 +29,11 @@ public class UltraLightClassLoadingTestGenerated extends AbstractUltraLightClass
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/asJava/ultraLightClasses"), Pattern.compile("^(.+)\\.(kt|kts)$"), null, true);
}
@TestMetadata("annotationTargets_1_6.kt")
public void testAnnotationTargets_1_6() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/annotationTargets_1_6.kt");
}
@TestMetadata("annotationWithSetParamPropertyModifier.kt")
public void testAnnotationWithSetParamPropertyModifier() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/annotationWithSetParamPropertyModifier.kt");
@@ -149,6 +149,11 @@ public class UltraLightClassSanityTestGenerated extends AbstractUltraLightClassS
runTest("compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass.kt");
}
@TestMetadata("SpecialAnnotationsOnAnnotationClass_1_6.kt")
public void testSpecialAnnotationsOnAnnotationClass_1_6() throws Exception {
runTest("compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass_1_6.kt");
}
@TestMetadata("StubOrderForOverloads.kt")
public void testStubOrderForOverloads() throws Exception {
runTest("compiler/testData/asJava/lightClasses/StubOrderForOverloads.kt");
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext
import org.jetbrains.kotlin.asJava.builder.StubComputationTracker
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.asJava.elements.*
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
@@ -29,8 +28,10 @@ import org.jetbrains.kotlin.idea.caches.resolve.LightClassLazinessChecker.Tracke
import org.jetbrains.kotlin.idea.completion.test.withServiceRegistered
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
import org.jetbrains.kotlin.idea.perf.forceUsingOldLightClassesForTest
import org.jetbrains.kotlin.idea.test.CompilerTestDirectives
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.withCustomCompilerOptions
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
@@ -39,14 +40,13 @@ import org.jetbrains.kotlin.test.MockLibraryUtilExt
import org.jetbrains.kotlin.test.util.KtTestUtil
import org.jetbrains.kotlin.utils.keysToMap
import org.jetbrains.plugins.groovy.lang.psi.impl.stringValue
import org.junit.Assert
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
abstract class AbstractIdeLightClassTest : KotlinLightCodeInsightFixtureTestCase() {
fun doTest(unused: String) {
fun doTest(@Suppress("UNUSED_PARAMETER") unused: String) {
forceUsingOldLightClassesForTest()
val fileName = fileName()
val extraFilePath = when {
@@ -54,30 +54,31 @@ abstract class AbstractIdeLightClassTest : KotlinLightCodeInsightFixtureTestCase
else -> error("Invalid test data extension")
}
val testFiles = if (File(testDataPath, extraFilePath).isFile) listOf(fileName, extraFilePath) else listOf(fileName)
withCustomCompilerOptions(File(testDataPath, fileName).readText(), project, module) {
val testFiles = if (File(testDataPath, extraFilePath).isFile) listOf(fileName, extraFilePath) else listOf(fileName)
val lazinessMode = lazinessModeByFileText()
myFixture.configureByFiles(*testFiles.toTypedArray())
if ((myFixture.file as? KtFile)?.isScript() == true) {
ScriptConfigurationManager.updateScriptDependenciesSynchronously(myFixture.file)
}
val lazinessMode = lazinessModeByFileText()
myFixture.configureByFiles(*testFiles.toTypedArray())
if ((myFixture.file as? KtFile)?.isScript() == true) {
ScriptConfigurationManager.updateScriptDependenciesSynchronously(myFixture.file)
}
val ktFile = myFixture.file as KtFile
val testData = testDataFile()
testLightClass(
KotlinTestUtils.replaceExtension(testData, "java"),
testData,
{ LightClassTestCommon.removeEmptyDefaultImpls(it) },
{ fqName ->
val tracker = LightClassLazinessChecker.Tracker(fqName)
project.withServiceRegistered<StubComputationTracker, PsiClass?>(tracker) {
findClass(fqName, ktFile, project)?.apply {
LightClassLazinessChecker.check(this as KtLightClass, tracker, lazinessMode)
tracker.allowLevel(EXACT)
PsiElementChecker.checkPsiElementStructure(this)
val ktFile = myFixture.file as KtFile
val testData = testDataFile()
testLightClass(
KotlinTestUtils.replaceExtension(testData, "java"),
testData,
{ LightClassTestCommon.removeEmptyDefaultImpls(it) },
{ fqName ->
val tracker = LightClassLazinessChecker.Tracker(fqName)
project.withServiceRegistered<StubComputationTracker, PsiClass?>(tracker) {
findClass(fqName, ktFile, project)?.apply {
LightClassLazinessChecker.check(this as KtLightClass, tracker, lazinessMode)
tracker.allowLevel(EXACT)
PsiElementChecker.checkPsiElementStructure(this)
}
}
}
})
})
}
}
private fun lazinessModeByFileText(): LightClassLazinessChecker.Mode {
@@ -105,11 +106,16 @@ abstract class AbstractIdeCompiledLightClassTest : KotlinDaemonAnalyzerTestCase(
val filePathWithoutExtension = "${KtTestUtil.getTestsRoot(this::class.java)}/${getTestName(false)}"
val testFile =
File("$filePathWithoutExtension.kt").takeIf { it.exists() } ?: File("$filePathWithoutExtension.kts").takeIf { it.exists() }
?: error("Test file not found!")
Assert.assertNotNull("Test file not found!", testFile)
val extraOptions = KotlinTestUtils.parseDirectives(testFile.readText())[
CompilerTestDirectives.JVM_TARGET_DIRECTIVE.substringBefore(":")
]?.let { jvmTarget ->
listOf("-jvm-target", jvmTarget)
} ?: emptyList()
val libraryJar = MockLibraryUtilExt.compileJvmLibraryToJar(
testFile!!.canonicalPath, libName(),
testFile.canonicalPath, libName(),
extraOptions = extraOptions,
extraClasspath = listOf(ForTestCompileRuntime.jetbrainsAnnotationsForTests().path)
)
val jarUrl = "jar://" + FileUtilRt.toSystemIndependentName(libraryJar.absolutePath) + "!/"
@@ -123,11 +129,13 @@ abstract class AbstractIdeCompiledLightClassTest : KotlinDaemonAnalyzerTestCase(
val expectedFile = KotlinTestUtils.replaceExtension(
testDataFile, "compiled.java"
).let { if (it.exists()) it else KotlinTestUtils.replaceExtension(testDataFile, "java") }
testLightClass(expectedFile, testDataFile, { it }, {
findClass(it, null, project)?.apply {
PsiElementChecker.checkPsiElementStructure(this)
}
})
withCustomCompilerOptions(testDataFile.readText(), project, module) {
testLightClass(expectedFile, testDataFile, { it }, {
findClass(it, null, project)?.apply {
PsiElementChecker.checkPsiElementStructure(this)
}
})
}
}
}
@@ -149,6 +149,11 @@ public class IdeCompiledLightClassTestGenerated extends AbstractIdeCompiledLight
runTest("compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass.kt");
}
@TestMetadata("SpecialAnnotationsOnAnnotationClass_1_6.kt")
public void testSpecialAnnotationsOnAnnotationClass_1_6() throws Exception {
runTest("compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass_1_6.kt");
}
@TestMetadata("StubOrderForOverloads.kt")
public void testStubOrderForOverloads() throws Exception {
runTest("compiler/testData/asJava/lightClasses/StubOrderForOverloads.kt");
@@ -149,6 +149,11 @@ public class IdeLightClassTestGenerated extends AbstractIdeLightClassTest {
runTest("compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass.kt");
}
@TestMetadata("SpecialAnnotationsOnAnnotationClass_1_6.kt")
public void testSpecialAnnotationsOnAnnotationClass_1_6() throws Exception {
runTest("compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass_1_6.kt");
}
@TestMetadata("StubOrderForOverloads.kt")
public void testStubOrderForOverloads() throws Exception {
runTest("compiler/testData/asJava/lightClasses/StubOrderForOverloads.kt");