From b611facd7149e53532a5992edffc3fd28094d199 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Wed, 26 Sep 2018 16:09:57 +0300 Subject: [PATCH] Check if serialization plugin presents in the facet compiler classpath before applying extensions logic #KT-27166 Fixed --- .../jetbrains/kotlin/idea/core/moduleUtils.kt | 11 +++ idea/src/META-INF/kotlinx-serialization.xml | 8 +-- .../synthetic/idea/ExperimentalUtils.kt | 4 ++ .../android/synthetic/idea/PlatformUtil.kt | 19 ------ .../SerializationCodegenExtension.kt | 2 +- .../extensions/SerializationJsExtension.kt | 2 +- .../SerializationLoweringExtension.kt | 2 +- .../SerializationResolveExtension.kt | 2 +- .../SerializationIDECodegenExtensions.kt | 38 +++++++++++ .../SerializationIDEResolveExtension.kt | 67 +++++++++++++++++++ .../idea/KotlinSerializationImportHandler.kt | 9 ++- .../idea/SerializationSwitchUtils.kt | 22 ++++++ 12 files changed, 156 insertions(+), 30 deletions(-) delete mode 100644 plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/PlatformUtil.kt create mode 100644 plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDECodegenExtensions.kt create mode 100644 plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDEResolveExtension.kt create mode 100644 plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/SerializationSwitchUtils.kt diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/moduleUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/moduleUtils.kt index b426fadc854..65434a776c4 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/moduleUtils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/moduleUtils.kt @@ -7,8 +7,19 @@ package org.jetbrains.kotlin.idea.core import com.intellij.facet.FacetManager import com.intellij.openapi.module.Module +import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo +import org.jetbrains.kotlin.idea.caches.project.PlatformModuleInfo fun Module.isAndroidModule(): Boolean { val facets = FacetManager.getInstance(this).allFacets return facets.any { it.javaClass.simpleName == "AndroidFacet" } +} + +fun ModuleInfo.unwrapModuleSourceInfo(): ModuleSourceInfo? { + return when (this) { + is ModuleSourceInfo -> this + is PlatformModuleInfo -> this.platformModule + else -> null + } } \ No newline at end of file diff --git a/idea/src/META-INF/kotlinx-serialization.xml b/idea/src/META-INF/kotlinx-serialization.xml index 7ceed70f675..cda0cb08d86 100644 --- a/idea/src/META-INF/kotlinx-serialization.xml +++ b/idea/src/META-INF/kotlinx-serialization.xml @@ -1,8 +1,8 @@ - - - - + + + + diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/ExperimentalUtils.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/ExperimentalUtils.kt index 464cd45ce84..6136e7d431a 100644 --- a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/ExperimentalUtils.kt +++ b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/ExperimentalUtils.kt @@ -27,7 +27,9 @@ import org.jetbrains.kotlin.android.synthetic.AndroidCommandLineProcessor.Compan import org.jetbrains.kotlin.android.synthetic.AndroidCommandLineProcessor.Companion.DEFAULT_CACHE_IMPL_OPTION import org.jetbrains.kotlin.android.synthetic.AndroidComponentRegistrar.Companion.parseCacheImplementationType import org.jetbrains.kotlin.compiler.plugin.CliOption +import org.jetbrains.kotlin.idea.core.unwrapModuleSourceInfo import org.jetbrains.kotlin.idea.facet.KotlinFacet +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform private val ANNOTATION_OPTION_PREFIX = "plugin:$ANDROID_COMPILER_PLUGIN_ID:" @@ -51,6 +53,8 @@ private fun isTestMode(module: Module): Boolean { internal val Module.androidExtensionsIsEnabled: Boolean get() = isTestMode(this) || getOptionValueInFacet(ENABLED_OPTION) == "true" +internal fun ModuleInfo.findAndroidModuleInfo() = unwrapModuleSourceInfo()?.takeIf { it.platform is JvmPlatform } + internal val ModuleInfo.androidExtensionsIsEnabled: Boolean get() { val module = this.findAndroidModuleInfo()?.module ?: return false diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/PlatformUtil.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/PlatformUtil.kt deleted file mode 100644 index f854d45392d..00000000000 --- a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/synthetic/idea/PlatformUtil.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. 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.android.synthetic.idea - -import org.jetbrains.kotlin.analyzer.ModuleInfo -import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo -import org.jetbrains.kotlin.idea.caches.project.PlatformModuleInfo -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform - -internal fun ModuleInfo.findAndroidModuleInfo(): ModuleSourceInfo? { - return when (this) { - is ModuleSourceInfo -> this.takeIf { it.platform is JvmPlatform } - is PlatformModuleInfo -> this.platformModule.takeIf { it.platform is JvmPlatform } - else -> null - } -} \ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationCodegenExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationCodegenExtension.kt index 5b3a45aeaa7..8ea648b00fd 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationCodegenExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationCodegenExtension.kt @@ -23,7 +23,7 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCode import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializableCompanionCodegenImpl import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.SerializerCodegenImpl -class SerializationCodegenExtension : ExpressionCodegenExtension { +open class SerializationCodegenExtension : ExpressionCodegenExtension { override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) { SerialInfoCodegenImpl.generateSerialInfoImplBody(codegen) SerializableCodegenImpl.generateSerializableExtensions(codegen) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationJsExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationJsExtension.kt index 4d447a27a22..445ee49cd31 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationJsExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationJsExtension.kt @@ -25,7 +25,7 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.js.SerializableCompa import org.jetbrains.kotlinx.serialization.compiler.backend.js.SerializableJsTranslator import org.jetbrains.kotlinx.serialization.compiler.backend.js.SerializerJsTranslator -class SerializationJsExtension: JsSyntheticTranslateExtension { +open class SerializationJsExtension: JsSyntheticTranslateExtension { override fun generateClassSyntheticParts(declaration: KtPureClassOrObject, descriptor: ClassDescriptor, translator: DeclarationBodyVisitor, context: TranslationContext) { SerializerJsTranslator.translate(declaration, descriptor, translator, context) SerializableJsTranslator.translate(declaration, descriptor, translator, context) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt index 4076d78dd21..c61ee56c756 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt @@ -49,7 +49,7 @@ private class SerializerClassLowering( } } -class SerializationLoweringExtension : IrGenerationExtension { +open class SerializationLoweringExtension : IrGenerationExtension { override fun generate( file: IrFile, backendContext: BackendContext, diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt index 30d216305ec..52d784797f3 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt @@ -30,7 +30,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoFqName import java.util.* -class SerializationResolveExtension : SyntheticResolveExtension { +open class SerializationResolveExtension : SyntheticResolveExtension { override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List = when { thisDescriptor.annotations.hasAnnotation(serialInfoFqName) -> listOf(SerialEntityNames.IMPL_NAME) thisDescriptor.isInternalSerializable && !thisDescriptor.hasCompanionObjectAsSerializer -> diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDECodegenExtensions.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDECodegenExtensions.kt new file mode 100644 index 00000000000..57019efaca8 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDECodegenExtensions.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.kotlinx.serialization.compiler.extensions + +import org.jetbrains.kotlin.backend.common.BackendContext +import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.js.translate.context.TranslationContext +import org.jetbrains.kotlin.js.translate.declaration.DeclarationBodyVisitor +import org.jetbrains.kotlin.psi.KtPureClassOrObject +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlinx.serialization.idea.runIfEnabledOn + +class SerializationIDECodegenExtension : SerializationCodegenExtension() { + override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) = + runIfEnabledOn(codegen.descriptor) { super.generateClassSyntheticParts(codegen) } +} + +class SerializationIDEJsExtension : SerializationJsExtension() { + override fun generateClassSyntheticParts( + declaration: KtPureClassOrObject, + descriptor: ClassDescriptor, + translator: DeclarationBodyVisitor, + context: TranslationContext + ) = runIfEnabledOn(descriptor) { + super.generateClassSyntheticParts(declaration, descriptor, translator, context) + } +} + +class SerializationIDEIrExtension : SerializationLoweringExtension() { + override fun generate(file: IrFile, backendContext: BackendContext, bindingContext: BindingContext) { + /* No-op – don't enable IR extensions in IDE */ + } +} \ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDEResolveExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDEResolveExtension.kt new file mode 100644 index 00000000000..43123ef658c --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationIDEResolveExtension.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.kotlinx.serialization.compiler.extensions + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.lazy.LazyClassContext +import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlinx.serialization.idea.getIfEnabledOn +import org.jetbrains.kotlinx.serialization.idea.runIfEnabledOn +import java.util.* + +class SerializationIDEResolveExtension : SerializationResolveExtension() { + override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List = + getIfEnabledOn(thisDescriptor) { super.getSyntheticNestedClassNames(thisDescriptor) } ?: emptyList() + + override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List = + getIfEnabledOn(thisDescriptor) { super.getSyntheticFunctionNames(thisDescriptor) } ?: emptyList() + + override fun generateSyntheticClasses( + thisDescriptor: ClassDescriptor, + name: Name, + ctx: LazyClassContext, + declarationProvider: ClassMemberDeclarationProvider, + result: MutableSet + ) = runIfEnabledOn(thisDescriptor) { + super.generateSyntheticClasses(thisDescriptor, name, ctx, declarationProvider, result) + } + + override fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name? = getIfEnabledOn(thisDescriptor) { + super.getSyntheticCompanionObjectNameIfNeeded(thisDescriptor) + } + + override fun addSyntheticSupertypes(thisDescriptor: ClassDescriptor, supertypes: MutableList) = + runIfEnabledOn(thisDescriptor) { + super.addSyntheticSupertypes(thisDescriptor, supertypes) + } + + override fun generateSyntheticMethods( + thisDescriptor: ClassDescriptor, + name: Name, + bindingContext: BindingContext, + fromSupertypes: List, + result: MutableCollection + ) = runIfEnabledOn(thisDescriptor) { + super.generateSyntheticMethods(thisDescriptor, name, bindingContext, fromSupertypes, result) + } + + override fun generateSyntheticProperties( + thisDescriptor: ClassDescriptor, + name: Name, + bindingContext: BindingContext, + fromSupertypes: ArrayList, + result: MutableSet + ) = runIfEnabledOn(thisDescriptor) { + super.generateSyntheticProperties(thisDescriptor, name, bindingContext, fromSupertypes, result) + } +} + + diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/KotlinSerializationImportHandler.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/KotlinSerializationImportHandler.kt index f6e320832ed..687481cee99 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/KotlinSerializationImportHandler.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/KotlinSerializationImportHandler.kt @@ -22,22 +22,25 @@ import org.jetbrains.kotlin.idea.facet.KotlinFacet import java.io.File internal object KotlinSerializationImportHandler { - private val PLUGIN_JPS_JAR :String + val PLUGIN_JPS_JAR :String get() = File(PathUtil.getJarPathForClass(this::class.java)).absolutePath fun modifyCompilerArguments(facet: KotlinFacet, buildSystemPluginJar: String) { val facetSettings = facet.configuration.settings val commonArguments = facetSettings.compilerArguments ?: CommonCompilerArguments.DummyImpl() + var pluginWasEnabled = false val oldPluginClasspaths = (commonArguments.pluginClasspaths ?: emptyArray()).filterTo(mutableListOf()) { val lastIndexOfFile = it.lastIndexOfAny(charArrayOf('/', File.separatorChar)) if (lastIndexOfFile < 0) { return@filterTo true } - !it.drop(lastIndexOfFile + 1).matches("$buildSystemPluginJar-.*\\.jar".toRegex()) + val match = it.drop(lastIndexOfFile + 1).matches("$buildSystemPluginJar-.*\\.jar".toRegex()) + if (match) pluginWasEnabled = true + !match } - val newPluginClasspaths = oldPluginClasspaths + PLUGIN_JPS_JAR + val newPluginClasspaths = if (pluginWasEnabled) oldPluginClasspaths + PLUGIN_JPS_JAR else oldPluginClasspaths commonArguments.pluginClasspaths = newPluginClasspaths.toTypedArray() facetSettings.compilerArguments = commonArguments } diff --git a/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/SerializationSwitchUtils.kt b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/SerializationSwitchUtils.kt new file mode 100644 index 00000000000..565f016b57e --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-ide/src/org/jetbrains/kotlinx/serialization/idea/SerializationSwitchUtils.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. 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.kotlinx.serialization.idea + +import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.idea.core.unwrapModuleSourceInfo +import org.jetbrains.kotlin.idea.facet.KotlinFacet +import org.jetbrains.kotlin.resolve.descriptorUtil.module + +fun getIfEnabledOn(clazz: ClassDescriptor, body: () -> T): T? { + val module = clazz.module.getCapability(ModuleInfo.Capability)?.unwrapModuleSourceInfo()?.module ?: return null + val facet = KotlinFacet.get(module) ?: return null + val pluginClasspath = facet.configuration.settings.compilerArguments?.pluginClasspaths ?: return null + if (pluginClasspath.none { it == KotlinSerializationImportHandler.PLUGIN_JPS_JAR }) return null + return body() +} + +fun runIfEnabledOn(clazz: ClassDescriptor, body: () -> Unit) { getIfEnabledOn(clazz, body) } \ No newline at end of file