Add CodegenApplicabilityCheckerExtension and use it to fallback to Heavy LigthClasses

+ Fixed #KT-33584
This commit is contained in:
Igor Yakovlev
2019-09-05 21:43:08 +03:00
parent f3b7d2fca9
commit 2b7dee6f8d
23 changed files with 528 additions and 138 deletions
+33 -1
View File
@@ -7,6 +7,7 @@ plugins {
}
dependencies {
testRuntime(project(":kotlin-reflect"))
compile(project(":kotlin-allopen-compiler-plugin"))
compile(project(":compiler:util"))
compile(project(":compiler:frontend"))
@@ -18,11 +19,42 @@ dependencies {
compileOnly(intellijDep())
excludeInAndroidStudio(rootProject) { compileOnly(intellijPluginDep("maven")) }
compileOnly(intellijPluginDep("gradle"))
testCompileOnly(project(":kotlin-serialization"))
testCompileOnly(project(":plugins:lint"))
testCompileOnly(project(":plugins:kapt3-idea"))
testCompileOnly(project(":plugins:android-extensions-compiler"))
testCompileOnly(project(":kotlin-android-extensions"))
testCompileOnly(project(":kotlin-android-extensions-runtime"))
testCompileOnly(project(":plugins:android-extensions-ide"))
testCompileOnly(project(":kotlin-allopen-compiler-plugin"))
testCompileOnly(project(":allopen-ide-plugin"))
testCompileOnly(project(":kotlin-imports-dumper-compiler-plugin"))
testCompileOnly(project(":kotlin-source-sections-compiler-plugin"))
testCompileOnly(project(":kotlinx-serialization-compiler-plugin"))
testCompileOnly(project(":kotlinx-serialization-ide-plugin"))
testCompileOnly(project(":kotlin-sam-with-receiver-compiler-plugin"))
testCompileOnly(project(":noarg-ide-plugin"))
testCompileOnly(project(":sam-with-receiver-ide-plugin"))
testCompileOnly(project(":idea:idea-native"))
testCompileOnly(project(":idea:idea-gradle-native"))
testCompileOnly(projectTests(":idea:idea-test-framework"))
testCompileOnly(intellijDep())
testRuntimeOnly(intellijDep())
Platform[192].orHigher {
testCompileOnly(intellijPluginDep("java"))
testRuntimeOnly(intellijPluginDep("java"))
}
}
sourceSets {
"main" { projectDefault() }
"test" {}
"test" { projectDefault() }
}
runtimeJar()
projectTest(parallel = true) {
}
@@ -17,45 +17,27 @@
package org.jetbrains.kotlin.allopen.ide
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootModificationTracker
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.allopen.AbstractAllOpenDeclarationAttributeAltererExtension
import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.allopen.AllOpenCommandLineProcessor.Companion.PLUGIN_ID
import org.jetbrains.kotlin.allopen.AllOpenCommandLineProcessor.Companion.ANNOTATION_OPTION
import org.jetbrains.kotlin.annotation.plugin.ide.getSpecialAnnotations
import java.util.concurrent.ConcurrentMap
import org.jetbrains.kotlin.allopen.AllOpenCommandLineProcessor.Companion.PLUGIN_ID
import org.jetbrains.kotlin.annotation.plugin.ide.AnnotationBasedLightClassApplicabilityExtension
import org.jetbrains.kotlin.annotation.plugin.ide.CachedAnnotationNames
import org.jetbrains.kotlin.annotation.plugin.ide.getAnnotationNames
import org.jetbrains.kotlin.psi.KtModifierListOwner
class IdeAllOpenDeclarationAttributeAltererExtension(val project: Project) : AbstractAllOpenDeclarationAttributeAltererExtension() {
private companion object {
val ANNOTATION_OPTION_PREFIX = "plugin:$PLUGIN_ID:${ANNOTATION_OPTION.optionName}="
}
internal val ALL_OPEN_ANNOTATION_OPTION_PREFIX = "plugin:$PLUGIN_ID:${ANNOTATION_OPTION.optionName}="
private val cache: CachedValue<ConcurrentMap<Module, List<String>>> = cachedValue(project) {
CachedValueProvider.Result.create(
ContainerUtil.createConcurrentWeakMap<Module, List<String>>(),
ProjectRootModificationTracker.getInstance(project)
)
}
class IdeAllOpenApplicabilityExtension(project: Project) :
AnnotationBasedLightClassApplicabilityExtension(project, ALL_OPEN_ANNOTATION_OPTION_PREFIX)
class IdeAllOpenDeclarationAttributeAltererExtension(val project: Project) :
AbstractAllOpenDeclarationAttributeAltererExtension() {
private val cachedAnnotationsNames = CachedAnnotationNames(project, ALL_OPEN_ANNOTATION_OPTION_PREFIX)
override fun getAnnotationFqNames(modifierListOwner: KtModifierListOwner?): List<String> {
if (ApplicationManager.getApplication().isUnitTestMode) {
return ANNOTATIONS_FOR_TESTS
}
if (modifierListOwner == null) return emptyList()
val module = ModuleUtilCore.findModuleForPsiElement(modifierListOwner) ?: return emptyList()
return cache.value.getOrPut(module) { module.getSpecialAnnotations(ANNOTATION_OPTION_PREFIX) }
}
private fun <T> cachedValue(project: Project, result: () -> CachedValueProvider.Result<T>): CachedValue<T> {
return CachedValuesManager.getManager(project).createCachedValue(result, false)
return if (ApplicationManager.getApplication().isUnitTestMode) ANNOTATIONS_FOR_TESTS
else cachedAnnotationsNames.getAnnotationNames(modifierListOwner)
}
}
@@ -0,0 +1,70 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.noarg
import com.intellij.lang.jvm.JvmModifier
import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.allopen.AbstractAllOpenDeclarationAttributeAltererExtension
import org.jetbrains.kotlin.allopen.ide.ALL_OPEN_ANNOTATION_OPTION_PREFIX
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinProjectDescriptorWithFacet
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
import org.junit.runner.RunWith
@RunWith(JUnit3WithIdeaConfigurationRunner::class)
class TestNoArgForLightClass : KotlinLightCodeInsightFixtureTestCase() {
companion object {
val allOpenAnnotationName = AbstractAllOpenDeclarationAttributeAltererExtension.ANNOTATIONS_FOR_TESTS.first()
const val targetClassName = "TargetClassName"
}
override fun getProjectDescriptor(): LightProjectDescriptor =
KotlinProjectDescriptorWithFacet(LanguageVersion.LATEST_STABLE, multiPlatform = false)
override fun setUp() {
super.setUp()
val facet = KotlinFacet.get(module) ?: error { "Facet not found" }
val configurationArguments = facet.configuration.settings.compilerArguments ?: error { "CompilerArguments not found" }
configurationArguments.pluginClasspaths = arrayOf("SomeClasspath")
configurationArguments.pluginOptions = arrayOf("$ALL_OPEN_ANNOTATION_OPTION_PREFIX$allOpenAnnotationName")
}
fun testAllOpenAnnotation() {
val file = myFixture.configureByText(
"A.kt",
"annotation class $allOpenAnnotationName\n"
+ "@$allOpenAnnotationName class $targetClassName(val e: Int)\n {"
+ " fun a() {}\n"
+ " val b = 32\n"
+ "}"
) as KtFile
val classes = file.classes
assertEquals(2, classes.size)
val targetClass = classes.firstOrNull { it.name == targetClassName }
?: error { "Expected class $targetClassName not found" }
assertFalse(targetClass.hasModifier(JvmModifier.FINAL))
targetClass.methods
.filter { !it.isConstructor }
.forEach {
assertFalse(it.hasModifier(JvmModifier.FINAL))
}
}
}