Check if serialization plugin presents in the facet compiler classpath before applying extensions logic

#KT-27166 Fixed
This commit is contained in:
Leonid Startsev
2018-09-26 16:09:57 +03:00
parent 088cd4b5e3
commit b611facd71
12 changed files with 156 additions and 30 deletions
@@ -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
}
}
+4 -4
View File
@@ -1,8 +1,8 @@
<idea-plugin>
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<expressionCodegenExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationCodegenExtension"/>
<syntheticResolveExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationResolveExtension"/>
<jsSyntheticTranslateExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationJsExtension"/>
<irGenerationExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtension"/>
<expressionCodegenExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationIDECodegenExtension"/>
<syntheticResolveExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationIDEResolveExtension"/>
<jsSyntheticTranslateExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationIDEJsExtension"/>
<irGenerationExtension implementation="org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationIDEIrExtension"/>
</extensions>
</idea-plugin>
@@ -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
@@ -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
}
}
@@ -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)
@@ -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)
@@ -49,7 +49,7 @@ private class SerializerClassLowering(
}
}
class SerializationLoweringExtension : IrGenerationExtension {
open class SerializationLoweringExtension : IrGenerationExtension {
override fun generate(
file: IrFile,
backendContext: BackendContext,
@@ -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<Name> = when {
thisDescriptor.annotations.hasAnnotation(serialInfoFqName) -> listOf(SerialEntityNames.IMPL_NAME)
thisDescriptor.isInternalSerializable && !thisDescriptor.hasCompanionObjectAsSerializer ->
@@ -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 */
}
}
@@ -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<Name> =
getIfEnabledOn(thisDescriptor) { super.getSyntheticNestedClassNames(thisDescriptor) } ?: emptyList()
override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> =
getIfEnabledOn(thisDescriptor) { super.getSyntheticFunctionNames(thisDescriptor) } ?: emptyList()
override fun generateSyntheticClasses(
thisDescriptor: ClassDescriptor,
name: Name,
ctx: LazyClassContext,
declarationProvider: ClassMemberDeclarationProvider,
result: MutableSet<ClassDescriptor>
) = 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<KotlinType>) =
runIfEnabledOn(thisDescriptor) {
super.addSyntheticSupertypes(thisDescriptor, supertypes)
}
override fun generateSyntheticMethods(
thisDescriptor: ClassDescriptor,
name: Name,
bindingContext: BindingContext,
fromSupertypes: List<SimpleFunctionDescriptor>,
result: MutableCollection<SimpleFunctionDescriptor>
) = runIfEnabledOn(thisDescriptor) {
super.generateSyntheticMethods(thisDescriptor, name, bindingContext, fromSupertypes, result)
}
override fun generateSyntheticProperties(
thisDescriptor: ClassDescriptor,
name: Name,
bindingContext: BindingContext,
fromSupertypes: ArrayList<PropertyDescriptor>,
result: MutableSet<PropertyDescriptor>
) = runIfEnabledOn(thisDescriptor) {
super.generateSyntheticProperties(thisDescriptor, name, bindingContext, fromSupertypes, result)
}
}
@@ -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
}
@@ -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 <T> 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<Unit>(clazz, body) }