Override/Implement Members: Copy @Experimental-annotated annotations

#KT-22922 Fixed
This commit is contained in:
Alexey Sedunov
2018-04-06 16:56:30 +03:00
parent c1d8ba9c2b
commit c7e72af170
11 changed files with 123 additions and 48 deletions
@@ -66,7 +66,7 @@ class ExperimentalUsageChecker(project: Project) : CallChecker {
}
companion object {
internal val EXPERIMENTAL_FQ_NAME = FqName("kotlin.Experimental")
val EXPERIMENTAL_FQ_NAME = FqName("kotlin.Experimental")
internal val USE_EXPERIMENTAL_FQ_NAME = FqName("kotlin.UseExperimental")
internal val USE_EXPERIMENTAL_ANNOTATION_CLASS = Name.identifier("markerClass")
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
@@ -190,6 +191,7 @@ interface DescriptorRendererOptions {
var textFormat: RenderingFormat
var excludedAnnotationClasses: Set<FqName>
var excludedTypeAnnotationClasses: Set<FqName>
var annotationFilter: ((AnnotationDescriptor) -> Boolean)?
var annotationArgumentsRenderingPolicy: AnnotationArgumentsRenderingPolicy
val includeAnnotationArguments: Boolean get() = annotationArgumentsRenderingPolicy.includeAnnotationArguments
@@ -396,8 +396,9 @@ internal class DescriptorRendererImpl(
val excluded = if (annotated is KotlinType) excludedTypeAnnotationClasses else excludedAnnotationClasses
val annotationFilter = annotationFilter
for ((annotation, target) in annotated.annotations.getAllAnnotations()) {
if (annotation.fqName !in excluded) {
if (annotation.fqName !in excluded && (annotationFilter == null || annotationFilter(annotation))) {
append(renderAnnotation(annotation, target)).append(" ")
}
}
@@ -17,6 +17,8 @@
package org.jetbrains.kotlin.renderer
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.types.KotlinType
import java.lang.IllegalStateException
@@ -98,6 +100,8 @@ internal class DescriptorRendererOptionsImpl : DescriptorRendererOptions {
override var excludedTypeAnnotationClasses by property(ExcludedTypeAnnotations.internalAnnotationsForResolve)
override var annotationFilter: ((AnnotationDescriptor) -> Boolean)? by property(null)
override var annotationArgumentsRenderingPolicy by property(AnnotationArgumentsRenderingPolicy.NO_ARGUMENTS)
override var alwaysRenderModifiers by property(false)
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.psi.findDocComment.findDocComment
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
import org.jetbrains.kotlin.renderer.*
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden
interface OverrideMemberChooserObject : ClassMember {
@@ -138,13 +139,16 @@ fun OverrideMemberChooserObject.generateMember(targetClass: KtClassOrObject, cop
private val OVERRIDE_RENDERER = DescriptorRenderer.withOptions {
defaultParameterValueRenderer = null
modifiers = setOf(DescriptorRendererModifier.OVERRIDE)
modifiers = setOf(DescriptorRendererModifier.OVERRIDE, DescriptorRendererModifier.ANNOTATIONS)
withDefinedIn = false
classifierNamePolicy = ClassifierNamePolicy.SOURCE_CODE_QUALIFIED
overrideRenderingPolicy = OverrideRenderingPolicy.RENDER_OVERRIDE
unitReturnType = false
typeNormalizer = IdeDescriptorRenderers.APPROXIMATE_FLEXIBLE_TYPES
renderUnabbreviatedType = false
annotationFilter = {
it.type.constructor.declarationDescriptor?.annotations?.hasAnnotation(ExperimentalUsageChecker.EXPERIMENTAL_FQ_NAME) ?: false
}
}
private fun PropertyDescriptor.wrap(): PropertyDescriptor {
@@ -28,11 +28,11 @@ import com.intellij.psi.search.ProjectScope
import com.intellij.testFramework.LightProjectDescriptor
import com.intellij.testFramework.LoggedErrorProcessor
import org.apache.log4j.Logger
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.actions.internal.KotlinInternalMode
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.facet.configureFacet
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
import org.jetbrains.kotlin.psi.KtFile
@@ -186,30 +186,44 @@ fun configureCompilerOptions(fileText: String, project: Project, module: Module)
val version = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// LANGUAGE_VERSION: ")
val jvmTarget = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// JVM_TARGET: ")
val options = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// COMPILER_ARGUMENTS: ")
if (version != null || jvmTarget != null || options != null) {
val accessToken = WriteAction.start()
try {
val modelsProvider = IdeModifiableModelsProviderImpl(project)
val facet = module.getOrCreateFacet(modelsProvider, useProjectSettings = false)
facet.configureFacet(
version ?: LanguageVersion.LATEST_STABLE.versionString,
LanguageFeature.State.DISABLED,
if (jvmTarget != null) TargetPlatformKind.Jvm(JvmTarget.fromString(jvmTarget)!!) else null,
modelsProvider
)
if (options != null) {
val compilerSettings = facet.configuration.settings.compilerSettings ?: CompilerSettings().also {
facet.configuration.settings.compilerSettings = it
}
compilerSettings.additionalArguments = options
facet.configuration.settings.updateMergedArguments()
if (version != null || jvmTarget != null || options != null) {
configureLanguageAndApiVersion(project, module, version ?: LanguageVersion.LATEST_STABLE.versionString)
val facetSettings = KotlinFacet.get(module)!!.configuration.settings
if (jvmTarget != null) {
(facetSettings.compilerArguments as K2JVMCompilerArguments).jvmTarget = jvmTarget
}
if (options != null) {
val compilerSettings = facetSettings.compilerSettings ?: CompilerSettings().also {
facetSettings.compilerSettings = it
}
modelsProvider.commit()
compilerSettings.additionalArguments = options
facetSettings.updateMergedArguments()
}
finally {
accessToken.finish()
}
}
fun configureLanguageAndApiVersion(
project: Project,
module: Module,
languageVersion: String,
apiVersion: String? = null
) {
val accessToken = WriteAction.start()
try {
val modelsProvider = IdeModifiableModelsProviderImpl(project)
val facet = module.getOrCreateFacet(modelsProvider, useProjectSettings = false)
facet.configureFacet(languageVersion, LanguageFeature.State.DISABLED, null, modelsProvider)
if (apiVersion != null) {
facet.configuration.settings.apiLevel = LanguageVersion.fromVersionString(apiVersion)
}
modelsProvider.commit()
}
finally {
accessToken.finish()
}
}
@@ -28,11 +28,11 @@ import com.intellij.psi.search.ProjectScope
import com.intellij.testFramework.LightProjectDescriptor
import com.intellij.testFramework.LoggedErrorProcessor
import org.apache.log4j.Logger
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.actions.internal.KotlinInternalMode
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.facet.configureFacet
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
import org.jetbrains.kotlin.psi.KtFile
@@ -185,30 +185,44 @@ fun configureCompilerOptions(fileText: String, project: Project, module: Module)
val version = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// LANGUAGE_VERSION: ")
val jvmTarget = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// JVM_TARGET: ")
val options = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// COMPILER_ARGUMENTS: ")
if (version != null || jvmTarget != null || options != null) {
val accessToken = WriteAction.start()
try {
val modelsProvider = IdeModifiableModelsProviderImpl(project)
val facet = module.getOrCreateFacet(modelsProvider, useProjectSettings = false)
facet.configureFacet(
version ?: LanguageVersion.LATEST_STABLE.versionString,
LanguageFeature.State.DISABLED,
if (jvmTarget != null) TargetPlatformKind.Jvm(JvmTarget.fromString(jvmTarget)!!) else null,
modelsProvider
)
if (options != null) {
val compilerSettings = facet.configuration.settings.compilerSettings ?: CompilerSettings().also {
facet.configuration.settings.compilerSettings = it
}
compilerSettings.additionalArguments = options
facet.configuration.settings.updateMergedArguments()
}
modelsProvider.commit()
if (version != null) {
configureLanguageAndApiVersion(project, module, version)
}
val facetSettings = KotlinFacet.get(module)!!.configuration.settings
if (jvmTarget != null) {
(facetSettings.compilerArguments as K2JVMCompilerArguments).jvmTarget = jvmTarget
}
if (options != null) {
val compilerSettings = facetSettings.compilerSettings ?: CompilerSettings().also {
facetSettings.compilerSettings = it
}
finally {
accessToken.finish()
compilerSettings.additionalArguments = options
facetSettings.updateMergedArguments()
}
}
fun configureLanguageAndApiVersion(
project: Project,
module: Module,
languageVersion: String,
apiVersion: String? = null
) {
val accessToken = WriteAction.start()
try {
val modelsProvider = IdeModifiableModelsProviderImpl(project)
val facet = module.getOrCreateFacet(modelsProvider, useProjectSettings = false)
facet.configureFacet(languageVersion, LanguageFeature.State.DISABLED, null, modelsProvider)
if (apiVersion != null) {
facet.configuration.settings.apiLevel = LanguageVersion.fromVersionString(apiVersion)
}
modelsProvider.commit()
}
finally {
accessToken.finish()
}
}
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.idea.decompiler.KotlinDecompiledFileViewProvider
import org.jetbrains.kotlin.idea.decompiler.KtDecompiledFile
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import java.util.*
enum class ModuleKind {
@@ -73,6 +74,8 @@ fun Module.configureAs(kind: ModuleKind) {
}
fun KtFile.dumpTextWithErrors(): String {
val text = text
if (InTextDirectivesUtils.isDirectiveDefined(text, "// DISABLE-ERRORS")) return text
val diagnostics = analyzeWithContent().diagnostics
val errors = diagnostics.filter { it.severity == Severity.ERROR }
if (errors.isEmpty()) return text
@@ -0,0 +1,12 @@
// DISABLE-ERRORS
@Experimental
annotation class FirstExperience
open class ParentTarget {
@FirstExperience open fun targetFun() {}
}
class ChildTarget : ParentTarget() {
<caret>
}
@@ -0,0 +1,15 @@
// DISABLE-ERRORS
@Experimental
annotation class FirstExperience
open class ParentTarget {
@FirstExperience open fun targetFun() {}
}
class ChildTarget : ParentTarget() {
@FirstExperience
override fun targetFun() {
<selection><caret>super.targetFun()</selection>
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.codeInsight
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.configureLanguageAndApiVersion
class OverrideImplementTest : AbstractOverrideImplementTest() {
override fun setUp() {
@@ -279,4 +280,9 @@ class OverrideImplementTest : AbstractOverrideImplementTest() {
fun testDataClassEquals() {
doOverrideFileTest("equals")
}
fun testCopyExperimental() {
configureLanguageAndApiVersion(project, module, "1.3", "1.3")
doOverrideFileTest("targetFun")
}
}