From 84eff43b49542a49e9cbe88d263861956ba546da Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Thu, 20 Jul 2017 21:05:46 +0300 Subject: [PATCH] Parcelable: Support Android Extensions experimental flag --- idea/src/META-INF/android.xml | 4 +-- .../parcel/ParcelableCodegenExtension.kt | 10 ++++++- .../parcel/ParcelableResolveExtension.kt | 23 +++++++++++++-- .../synthetic/AndroidComponentRegistrar.kt | 6 ++-- .../parcel/IDEParcelableCodegenExtension.kt | 28 +++++++++++++++++++ .../parcel/IDEParcelableResolveExtension.kt | 28 +++++++++++++++++++ 6 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/IDEParcelableCodegenExtension.kt create mode 100644 plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/IDEParcelableResolveExtension.kt diff --git a/idea/src/META-INF/android.xml b/idea/src/META-INF/android.xml index a3adc8b67a5..46b3918e194 100644 --- a/idea/src/META-INF/android.xml +++ b/idea/src/META-INF/android.xml @@ -85,8 +85,8 @@ - - + + diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt index 341e39716fa..3a538470308 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt @@ -39,6 +39,8 @@ import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation.* import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.DescriptorFactory import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.module @@ -50,7 +52,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes.* import org.jetbrains.org.objectweb.asm.Type import java.io.FileDescriptor -class ParcelableCodegenExtension : ExpressionCodegenExtension { +open class ParcelableCodegenExtension : ExpressionCodegenExtension { private companion object { private val FILE_DESCRIPTOR_FQNAME = FqName(FileDescriptor::class.java.canonicalName) private val PARCELER_FQNAME = FqName(Parceler::class.java.canonicalName) @@ -58,9 +60,15 @@ class ParcelableCodegenExtension : ExpressionCodegenExtension { fun KotlinType.isParceler() = constructor.declarationDescriptor?.fqNameSafe == PARCELER_FQNAME } + protected open fun isExperimental(element: KtElement) = true + override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) { val parcelableClass = codegen.descriptor if (!parcelableClass.isMagicParcelable) return + + val sourceElement = (codegen.myClass as? KtClassOrObject) ?: return + if (!isExperimental(sourceElement)) return + assert(parcelableClass.kind == ClassKind.CLASS || parcelableClass.kind == ClassKind.OBJECT) val propertiesToSerialize = getPropertiesToSerialize(codegen, parcelableClass) diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableResolveExtension.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableResolveExtension.kt index 77b70a1ff4d..568775fbc72 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableResolveExtension.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableResolveExtension.kt @@ -26,14 +26,16 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension +import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.SimpleType -class ParcelableResolveExtension : SyntheticResolveExtension { +open class ParcelableResolveExtension : SyntheticResolveExtension { companion object { fun resolveParcelClassType(module: ModuleDescriptor): SimpleType { return module.findClassAcrossModuleDependencies( @@ -72,6 +74,8 @@ class ParcelableResolveExtension : SyntheticResolveExtension { } } + protected open fun isExperimental(element: KtElement) = true + override fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor) = null override fun generateSyntheticMethods( @@ -80,9 +84,22 @@ class ParcelableResolveExtension : SyntheticResolveExtension { fromSupertypes: List, result: MutableCollection ) { - if (name.asString() == DESCRIBE_CONTENTS.methodName && clazz.isMagicParcelable && result.none { it.isDescribeContents() }) { + fun isExperimental(): Boolean { + val sourceElement = (clazz.source as? PsiSourceElement)?.psi as? KtElement ?: return false + return isExperimental(sourceElement) + } + + if (name.asString() == DESCRIBE_CONTENTS.methodName + && clazz.isMagicParcelable + && isExperimental() + && result.none { it.isDescribeContents() } + ) { result += createMethod(clazz, DESCRIBE_CONTENTS, clazz.builtIns.intType) - } else if (name.asString() == WRITE_TO_PARCEL.methodName && clazz.isMagicParcelable && result.none { it.isWriteToParcel() }) { + } else if (name.asString() == WRITE_TO_PARCEL.methodName + && clazz.isMagicParcelable + && isExperimental() + && result.none { it.isWriteToParcel() } + ) { val builtIns = clazz.builtIns val parcelClassType = resolveParcelClassType(clazz.module) result += createMethod(clazz, WRITE_TO_PARCEL, builtIns.unitType, "parcel" to parcelClassType, "flags" to builtIns.intType) diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/AndroidComponentRegistrar.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/AndroidComponentRegistrar.kt index 1756d0bf8c3..f7573581f47 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/AndroidComponentRegistrar.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/AndroidComponentRegistrar.kt @@ -90,12 +90,14 @@ class AndroidComponentRegistrar : ComponentRegistrar { } override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) { - registerParcelExtensions(project) - val applicationPackage = configuration.get(AndroidConfigurationKeys.PACKAGE) val variants = configuration.get(AndroidConfigurationKeys.VARIANT)?.mapNotNull { parseVariant(it) } ?: emptyList() val isExperimental = configuration.get(AndroidConfigurationKeys.EXPERIMENTAL) == "true" + if (isExperimental) { + registerParcelExtensions(project) + } + if (variants.isNotEmpty() && !applicationPackage.isNullOrBlank()) { val layoutXmlFileManager = CliAndroidLayoutXmlFileManager(project, applicationPackage!!, variants) project.registerService(AndroidLayoutXmlFileManager::class.java, layoutXmlFileManager) diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/IDEParcelableCodegenExtension.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/IDEParcelableCodegenExtension.kt new file mode 100644 index 00000000000..133d932f0dc --- /dev/null +++ b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/IDEParcelableCodegenExtension.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.android.parcel + +import org.jetbrains.kotlin.android.synthetic.idea.androidExtensionsIsExperimental +import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo +import org.jetbrains.kotlin.psi.KtElement + +class IDEParcelableCodegenExtension : ParcelableCodegenExtension() { + override fun isExperimental(element: KtElement): Boolean { + val moduleInfo = element.getModuleInfo() + return moduleInfo.androidExtensionsIsExperimental + } +} \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/IDEParcelableResolveExtension.kt b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/IDEParcelableResolveExtension.kt new file mode 100644 index 00000000000..e1f71b618f3 --- /dev/null +++ b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/parcel/IDEParcelableResolveExtension.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.android.parcel + +import org.jetbrains.kotlin.android.synthetic.idea.androidExtensionsIsExperimental +import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo +import org.jetbrains.kotlin.psi.KtElement + +class IDEParcelableResolveExtension : ParcelableResolveExtension() { + override fun isExperimental(element: KtElement): Boolean { + val moduleInfo = element.getModuleInfo() + return moduleInfo.androidExtensionsIsExperimental + } +} \ No newline at end of file