Parcelize: Add IDE support for the Parcelize compiler plugin with sources extracted from Android Extensions plugin (KT-40030)

This commit is contained in:
Yan Zhulanow
2020-07-07 19:35:26 +09:00
parent b7796d63d8
commit 15b2850ee0
85 changed files with 2473 additions and 2 deletions
+1
View File
@@ -58,6 +58,7 @@ dependencies {
testCompile(projectTests(":plugins:android-extensions-compiler"))
testCompile(projectTests(":plugins:android-extensions-ide"))
testCompile(projectTests(":plugins:parcelize:parcelize-compiler"))
testCompile(projectTests(":plugins:parcelize:parcelize-ide"))
testCompile(projectTests(":kotlin-annotation-processing"))
testCompile(projectTests(":kotlin-annotation-processing-cli"))
testCompile(projectTests(":kotlin-allopen-compiler-plugin"))
@@ -178,6 +178,8 @@ import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeBoxTest
import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeBytecodeListingTest
import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeIrBoxTest
import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeIrBytecodeListingTest
import org.jetbrains.kotlin.pacelize.ide.test.AbstractParcelizeCheckerTest
import org.jetbrains.kotlin.pacelize.ide.test.AbstractParcelizeQuickFixTest
import org.jetbrains.kotlin.psi.patternMatching.AbstractPsiUnifierTest
import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverScriptTest
import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverTest
@@ -1530,6 +1532,16 @@ fun main(args: Array<String>) {
}
}
testGroup("plugins/parcelize/parcelize-ide/tests", "plugins/parcelize/parcelize-ide/testData") {
testClass<AbstractParcelizeQuickFixTest> {
model("quickfix", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true)
}
testClass<AbstractParcelizeCheckerTest> {
model("checker", extension = "kt")
}
}
testGroup("plugins/jvm-abi-gen/test", "plugins/jvm-abi-gen/testData") {
testClass<AbstractCompareJvmAbiTest> {
model("compare", recursive = false, extension = null)
@@ -152,6 +152,8 @@ import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeBoxTest
import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeBytecodeListingTest
import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeIrBoxTest
import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeIrBytecodeListingTest
import org.jetbrains.kotlin.pacelize.ide.test.AbstractParcelizeCheckerTest
import org.jetbrains.kotlin.pacelize.ide.test.AbstractParcelizeQuickFixTest
import org.jetbrains.kotlin.psi.patternMatching.AbstractPsiUnifierTest
import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverScriptTest
import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverTest
@@ -1149,6 +1151,16 @@ fun main(args: Array<String>) {
}
}
testGroup("plugins/parcelize/parcelize-ide/tests", "plugins/parcelize/parcelize-ide/testData") {
testClass<AbstractParcelizeQuickFixTest> {
model("quickfix", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true)
}
testClass<AbstractParcelizeCheckerTest> {
model("checker", extension = "kt")
}
}
testGroup("plugins/kapt3/kapt3-compiler/test", "plugins/kapt3/kapt3-compiler/testData") {
testClass<AbstractClassFileToSourceStubConverterTest> {
model("converter")
@@ -152,6 +152,8 @@ import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeBoxTest
import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeBytecodeListingTest
import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeIrBoxTest
import org.jetbrains.kotlin.parcelize.test.AbstractParcelizeIrBytecodeListingTest
import org.jetbrains.kotlin.pacelize.ide.test.AbstractParcelizeCheckerTest
import org.jetbrains.kotlin.pacelize.ide.test.AbstractParcelizeQuickFixTest
import org.jetbrains.kotlin.psi.patternMatching.AbstractPsiUnifierTest
import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverScriptTest
import org.jetbrains.kotlin.samWithReceiver.AbstractSamWithReceiverTest
@@ -1149,6 +1151,16 @@ fun main(args: Array<String>) {
}
}
testGroup("plugins/parcelize/parcelize-ide/tests", "plugins/parcelize/parcelize-ide/testData") {
testClass<AbstractParcelizeQuickFixTest> {
model("quickfix", pattern = "^([\\w\\-_]+)\\.kt$", filenameStartsLowerCase = true)
}
testClass<AbstractParcelizeCheckerTest> {
model("checker", extension = "kt")
}
}
testGroup("plugins/kapt3/kapt3-compiler/test", "plugins/kapt3/kapt3-compiler/testData") {
testClass<AbstractClassFileToSourceStubConverterTest> {
model("converter")
@@ -5,4 +5,5 @@ org.jetbrains.kotlin.gradle.KotlinCommonizerModelBuilder
org.jetbrains.kotlin.allopen.ide.AllOpenModelBuilderService
org.jetbrains.kotlin.kapt.idea.KaptModelBuilderService
org.jetbrains.kotlin.noarg.ide.NoArgModelBuilderService
org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverModelBuilderService
org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverModelBuilderService
org.jetbrains.kotlin.parcelize.ide.ParcelizeModelBuilderService
@@ -0,0 +1,33 @@
/*
* Copyright 2010-2020 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.parcelize.ide
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.AbstractKotlinGradleModelBuilder
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
import java.io.Serializable
interface ParcelizeGradleModel : Serializable {
val isEnabled: Boolean
}
class ParcelizeGradleModelImpl(override val isEnabled: Boolean) : ParcelizeGradleModel
class ParcelizeModelBuilderService : AbstractKotlinGradleModelBuilder() {
override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder {
return ErrorMessageBuilder.create(project, e, "Gradle import errors")
.withDescription("Unable to build kotlin-parcelize plugin configuration")
}
override fun canBuild(modelName: String?): Boolean = modelName == ParcelizeGradleModel::class.java.name
override fun buildAll(modelName: String?, project: Project): Any {
val parcelizePlugin: Plugin<*>? = project.plugins.findPlugin("kotlin-parcelize")
return ParcelizeGradleModelImpl(isEnabled = parcelizePlugin != null)
}
}
@@ -68,6 +68,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<!-- CIDR-PLUGIN-EXCLUDE-START -->
<xi:include href="jvm-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="parcelize.xml" xpointer="xpointer(/idea-plugin/*)"/>
<!-- CIDR-PLUGIN-EXCLUDE-END -->
<xi:include href="native-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
@@ -68,6 +68,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<!-- CIDR-PLUGIN-EXCLUDE-START -->
<xi:include href="jvm-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="parcelize.xml" xpointer="xpointer(/idea-plugin/*)"/>
<!-- CIDR-PLUGIN-EXCLUDE-END -->
<xi:include href="native-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
@@ -68,6 +68,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<!-- CIDR-PLUGIN-EXCLUDE-START -->
<xi:include href="jvm-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="parcelize.xml" xpointer="xpointer(/idea-plugin/*)"/>
<!-- CIDR-PLUGIN-EXCLUDE-END -->
<xi:include href="native-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
@@ -67,6 +67,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<!-- CIDR-PLUGIN-EXCLUDE-START -->
<xi:include href="jvm-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="parcelize.xml" xpointer="xpointer(/idea-plugin/*)"/>
<!-- CIDR-PLUGIN-EXCLUDE-END -->
<xi:include href="native-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
@@ -67,6 +67,7 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<!-- CIDR-PLUGIN-EXCLUDE-START -->
<xi:include href="jvm-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="parcelize.xml" xpointer="xpointer(/idea-plugin/*)"/>
<!-- CIDR-PLUGIN-EXCLUDE-END -->
<xi:include href="native-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
+16
View File
@@ -0,0 +1,16 @@
<idea-plugin>
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<expressionCodegenExtension implementation="org.jetbrains.kotlin.parcelize.ide.IdeParcelizeCodegenExtension"/>
<irGenerationExtension implementation="org.jetbrains.kotlin.parcelize.ParcelizeIrGeneratorExtension"/>
<syntheticResolveExtension implementation="org.jetbrains.kotlin.parcelize.ide.IdeParcelizeResolveExtension"/>
<classBuilderFactoryInterceptorExtension implementation="org.jetbrains.kotlin.parcelize.ParcelizeClinitClassBuilderInterceptorExtension"/>
<storageComponentContainerContributor implementation="org.jetbrains.kotlin.parcelize.ParcelizeDeclarationCheckerComponentContainerContributor"/>
<ultraLightClassModifierExtension implementation="org.jetbrains.kotlin.parcelize.ide.ParcelizeUltraLightClassModifierExtension"/>
<quickFixContributor implementation="org.jetbrains.kotlin.parcelize.ide.quickfixes.ParcelizeQuickFixContributor"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<projectResolve implementation="org.jetbrains.kotlin.parcelize.ide.ParcelizeProjectResolverExtension" order="last"/>
</extensions>
</idea-plugin>
+2 -1
View File
@@ -76,4 +76,5 @@ org.jetbrains.kotlin.idea.quickfix.SpecifyOverrideExplicitlyFix
org.jetbrains.kotlin.idea.quickfix.SpecifyTypeExplicitlyFix
org.jetbrains.kotlin.idea.quickfix.SuperClassNotInitialized$AddParenthesisFix
org.jetbrains.kotlin.idea.quickfix.WrapWithSafeLetCallFix
com.intellij.spring.model.highlighting.autowire.SpringUastInjectionPointsAutowiringInspection$AddSpringBeanQualifierFix
com.intellij.spring.model.highlighting.autowire.SpringUastInjectionPointsAutowiringInspection$AddSpringBeanQualifierFix
org.jetbrains.kotlin.parcelize.ide.quickfixes.ParcelMigrateToParcelizeQuickFix
@@ -0,0 +1,63 @@
description = "IDE support for the Parcelize compiler plugin"
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
compile(project(":compiler:util"))
compile(project(":compiler:plugin-api"))
compile(project(":compiler:frontend"))
compile(project(":compiler:frontend.java"))
compile(project(":compiler:light-classes"))
compile(project(":idea"))
compile(project(":plugins:parcelize:parcelize-compiler"))
compile(project(":plugins:parcelize:parcelize-runtime"))
compile(intellijDep())
compile(intellijPluginDep("gradle"))
Platform[191].orLower {
compileOnly(intellijDep()) { includeJars("java-api", "java-impl") }
}
Platform[192].orHigher {
compileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
}
testCompile(projectTests(":idea"))
testCompile(projectTests(":plugins:parcelize:parcelize-compiler"))
testRuntime(project(":allopen-ide-plugin"))
testRuntime(project(":noarg-ide-plugin"))
testRuntime(project(":kotlin-scripting-idea")) { isTransitive = false }
testRuntime(project(":kotlin-scripting-compiler-impl"))
testRuntime(project(":sam-with-receiver-ide-plugin"))
testRuntime(project(":kotlinx-serialization-ide-plugin"))
testRuntime(toolsJar())
Platform[192].orHigher {
testRuntimeOnly(intellijPluginDep("java"))
}
}
sourceSets {
"main" { projectDefault() }
"test" { projectDefault() }
}
runtimeJar()
javadocJar()
sourcesJar()
testsJar {}
projectTest(parallel = true) {
dependsOn(":dist")
workingDir = rootDir
useAndroidJar()
}
apply(from = "$rootDir/gradle/kotlinPluginPublication.gradle.kts")
@@ -0,0 +1,8 @@
parcelize.fix.annotate.containing.class.with.parcelize=Annotate containing class with ''@Parcelize''
parcelize.fix.add.ignored.on.parcel.annotation=Add ''@IgnoredOnParcel'' annotation
parcelize.fix.add.empty.primary.constructor=Add empty primary constructor
parcelize.fix.add.parcelable.supertype=Add ''Parcelable'' supertype
parcelize.fix.remove.redundant.type.parceler.annotation=Remove redundant ''@TypeParceler'' annotation
parcelize.fix.migrate.to.parceler.companion.object=Migrate to ''Parceler'' companion object
parcelize.fix.remove.custom.creator.property=Remove custom ''CREATOR'' property
parcelize.fix.remove.custom.write.to.parcel.function=Remove custom ''writeToParcel()'' function
@@ -0,0 +1,15 @@
/*
* Copyright 2010-2020 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.parcelize.ide
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.parcelize.ParcelizeCodegenExtension
class IdeParcelizeCodegenExtension : ParcelizeCodegenExtension() {
override fun isAvailable(element: PsiElement): Boolean {
return ParcelizeAvailability.isAvailable(element)
}
}
@@ -0,0 +1,15 @@
/*
* Copyright 2010-2020 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.parcelize.ide
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.parcelize.ParcelizeResolveExtension
class IdeParcelizeResolveExtension : ParcelizeResolveExtension() {
override fun isAvailable(element: PsiElement): Boolean {
return ParcelizeAvailability.isAvailable(element)
}
}
@@ -0,0 +1,18 @@
/*
* Copyright 2010-2020 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.parcelize.ide
import org.jetbrains.annotations.NonNls
import org.jetbrains.annotations.PropertyKey
import org.jetbrains.kotlin.util.AbstractKotlinBundle
@NonNls
private const val BUNDLE = "messages.KotlinParcelizeBundle"
object KotlinParcelizeBundle : AbstractKotlinBundle(BUNDLE) {
@JvmStatic
fun message(@NonNls @PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String = getMessage(key, *params)
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2020 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.parcelize.ide
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
import com.intellij.openapi.module.Module
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil
import org.jetbrains.plugins.gradle.util.GradleConstants
object ParcelizeAvailability {
fun isAvailable(element: PsiElement): Boolean {
if (ApplicationManager.getApplication().isUnitTestMode) {
return true
}
val module = element.module ?: return false
return isAvailable(module)
}
fun isAvailable(module: Module): Boolean {
if (ApplicationManager.getApplication().isUnitTestMode) {
return true
}
val path = ExternalSystemApiUtil.getExternalProjectPath(module) ?: return false
val externalProjectInfo = ExternalSystemUtil.getExternalProjectInfo(module.project, GradleConstants.SYSTEM_ID, path) ?: return false
val moduleData = GradleProjectResolverUtil.findModule(externalProjectInfo.externalProjectStructure, path) ?: return false
return moduleData.getCopyableUserData(ParcelizeProjectResolverExtension.KEY).isEnabled
}
}
@@ -0,0 +1,33 @@
/*
* Copyright 2010-2020 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.parcelize.ide
import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.project.ModuleData
import com.intellij.openapi.util.Key
import org.gradle.tooling.model.idea.IdeaModule
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
@Suppress("unused")
class ParcelizeProjectResolverExtension : AbstractProjectResolverExtension() {
companion object {
val KEY = Key<ParcelizeGradleModel>("ParcelizeModel")
}
override fun getExtraProjectModelClasses() = setOf(ParcelizeGradleModel::class.java)
override fun getToolingExtensionsClasses() = setOf(ParcelizeModelBuilderService::class.java, Unit::class.java)
override fun populateModuleExtraModels(gradleModule: IdeaModule, ideModule: DataNode<ModuleData>) {
val parcelizeModel = resolverCtx.getExtraProject(gradleModule, ParcelizeGradleModel::class.java)
if (parcelizeModel != null) {
ideModule.putCopyableUserData(KEY, ParcelizeGradleModelImpl(isEnabled = parcelizeModel.isEnabled))
}
super.populateModuleExtraModels(gradleModule, ideModule)
}
}
@@ -0,0 +1,95 @@
/*
* 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.parcelize.ide
import com.intellij.psi.impl.light.LightFieldBuilder
import org.jetbrains.kotlin.parcelize.serializers.ParcelizeExtensionBase
import org.jetbrains.kotlin.asJava.UltraLightClassModifierExtension
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
import org.jetbrains.kotlin.asJava.classes.createGeneratedMethodFromDescriptor
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightFieldImpl
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.kotlin.parcelize.ParcelizeSyntheticComponent
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.util.isAnnotated
import org.jetbrains.kotlin.util.isOrdinaryClass
class ParcelizeUltraLightClassModifierExtension : ParcelizeExtensionBase, UltraLightClassModifierExtension {
private fun tryGetParcelizeClass(declaration: KtDeclaration, descriptor: Lazy<DeclarationDescriptor?>): ClassDescriptor? {
if (!declaration.isOrdinaryClass || !declaration.isAnnotated) {
return null
}
val module = declaration.module
if (module == null || !ParcelizeAvailability.isAvailable(module)) {
return null
}
val descriptorValue = descriptor.value ?: return null
val parcelizeClass = (descriptorValue as? ClassDescriptor) ?: descriptorValue.containingDeclaration as? ClassDescriptor
if (parcelizeClass == null || !parcelizeClass.isParcelizeClassDescriptor) {
return null
}
return parcelizeClass
}
override fun interceptFieldsBuilding(
declaration: KtDeclaration,
descriptor: Lazy<DeclarationDescriptor?>,
containingDeclaration: KtUltraLightClass,
fieldsList: MutableList<KtLightField>
) {
val parcelizeClass = tryGetParcelizeClass(declaration, descriptor) ?: return
if (parcelizeClass.hasCreatorField()) return
val fieldWrapper = KtLightFieldImpl.KtLightFieldForSourceDeclaration(
origin = null,
computeDelegate = {
LightFieldBuilder("CREATOR", "android.os.Parcelable.Creator", containingDeclaration).also {
it.setModifiers("public", "static", "final")
}
},
containingClass = containingDeclaration,
dummyDelegate = null
)
fieldsList.add(fieldWrapper)
}
override fun interceptMethodsBuilding(
declaration: KtDeclaration,
descriptor: Lazy<DeclarationDescriptor?>,
containingDeclaration: KtUltraLightClass,
methodsList: MutableList<KtLightMethod>
) {
val parcelizeClass = tryGetParcelizeClass(declaration, descriptor) ?: return
with(parcelizeClass) {
if (hasSyntheticDescribeContents()) {
findFunction(ParcelizeSyntheticComponent.ComponentKind.DESCRIBE_CONTENTS)?.let {
methodsList.add(
containingDeclaration.createGeneratedMethodFromDescriptor(it)
)
}
}
if (hasSyntheticWriteToParcel()) {
findFunction(ParcelizeSyntheticComponent.ComponentKind.WRITE_TO_PARCEL)?.let {
methodsList.add(
containingDeclaration.createGeneratedMethodFromDescriptor(it)
)
}
}
}
}
}
@@ -0,0 +1,53 @@
/*
* 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.parcelize.ide.quickfixes
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
abstract class AbstractParcelizeQuickFix<T : KtElement>(element: T) : KotlinQuickFixAction<T>(element) {
protected companion object {
fun <T : KtElement> T.shortenReferences() = ShortenReferences.DEFAULT.process(this)
}
override fun getFamilyName() = text
abstract fun invoke(ktPsiFactory: KtPsiFactory, element: T)
final override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val clazz = element ?: return
val ktPsiFactory = KtPsiFactory(project, markGenerated = true)
invoke(ktPsiFactory, clazz)
}
abstract class AbstractFactory(private val f: Diagnostic.() -> IntentionAction?) : KotlinSingleIntentionActionFactory() {
companion object {
inline fun <reified T : KtElement> Diagnostic.findElement() = psiElement.getNonStrictParentOfType<T>()
}
override fun createAction(diagnostic: Diagnostic) = f(diagnostic)
}
}
@@ -0,0 +1,40 @@
/*
* 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.parcelize.ide.quickfixes
import kotlinx.parcelize.Parcelize
import org.jetbrains.kotlin.idea.util.addAnnotation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.parcelize.diagnostic.ErrorsParcelize
import org.jetbrains.kotlin.parcelize.ide.KotlinParcelizeBundle
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtPsiFactory
class AnnotateWithParcelizeQuickFix(clazz: KtClassOrObject) : AbstractParcelizeQuickFix<KtClassOrObject>(clazz) {
object Factory : AbstractFactory(
{
val targetClass = ErrorsParcelize.CLASS_SHOULD_BE_PARCELIZE.cast(this).a
AnnotateWithParcelizeQuickFix(targetClass)
}
)
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.annotate.containing.class.with.parcelize")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtClassOrObject) {
element.addAnnotation(FqName(Parcelize::class.java.name))
}
}
@@ -0,0 +1,291 @@
/*
* 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.parcelize.ide.quickfixes
import com.intellij.openapi.diagnostic.Logger
import kotlinx.parcelize.Parceler
import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CREATOR_CLASS_FQNAME
import org.jetbrains.kotlin.parcelize.ANDROID_PARCEL_CLASS_FQNAME
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.core.getOrCreateCompanionObject
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.unwrapBlockOrParenthesis
import org.jetbrains.kotlin.idea.util.findAnnotation
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.parcelize.ide.KotlinParcelizeBundle
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.addRemoveModifier.setModifierList
import org.jetbrains.kotlin.psi.psiUtil.containingClass
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.types.TypeUtils
class ParcelMigrateToParcelizeQuickFix(function: KtClass) : AbstractParcelizeQuickFix<KtClass>(function) {
companion object {
private val PARCELER_FQNAME = FqName(Parceler::class.java.name)
private val PARCELER_WRITE_FUNCTION_NAME = Name.identifier("write")
private val PARCELER_CREATE_FUNCTION_NAME = Name.identifier("create")
private val LOG = Logger.getInstance(ParcelMigrateToParcelizeQuickFix::class.java)
private fun KtClass.findParcelerCompanionObject(): Pair<KtObjectDeclaration, ClassDescriptor>? {
for (obj in companionObjects) {
val objDescriptor = obj.resolveToDescriptorIfAny() ?: continue
for (superClassifier in objDescriptor.getAllSuperClassifiers()) {
val superClass = superClassifier as? ClassDescriptor ?: continue
if (superClass.fqNameSafe == PARCELER_FQNAME) return Pair(obj, objDescriptor)
}
}
return null
}
private fun KtNamedFunction.doesLookLikeWriteToParcelOverride(): Boolean {
return name == "writeToParcel"
&& hasModifier(KtTokens.OVERRIDE_KEYWORD)
&& receiverTypeReference == null
&& valueParameters.size == 2
&& typeParameters.size == 0
&& valueParameters[0].typeReference?.getFqName() == ANDROID_PARCEL_CLASS_FQNAME.asString()
&& valueParameters[1].typeReference?.getFqName() == StandardNames.FqNames._int.asString()
}
private fun KtNamedFunction.doesLookLikeNewArrayOverride(): Boolean {
return name == "newArray"
&& hasModifier(KtTokens.OVERRIDE_KEYWORD)
&& receiverTypeReference == null
&& valueParameters.size == 1
&& typeParameters.size == 0
&& valueParameters[0].typeReference?.getFqName() == StandardNames.FqNames._int.asString()
}
private fun KtNamedFunction.doesLookLikeDescribeContentsOverride(): Boolean {
return name == "describeContents"
&& hasModifier(KtTokens.OVERRIDE_KEYWORD)
&& receiverTypeReference == null
&& valueParameters.size == 0
&& typeParameters.size == 0
&& typeReference?.getFqName() == StandardNames.FqNames._int.asString()
}
private fun KtClass.findWriteToParcelOverride() = findFunction { doesLookLikeWriteToParcelOverride() }
private fun KtClass.findDescribeContentsOverride() = findFunction { doesLookLikeDescribeContentsOverride() }
private fun KtObjectDeclaration.findNewArrayOverride() = findFunction { doesLookLikeNewArrayOverride() }
private fun KtClass.findCreatorClass(): KtClassOrObject? {
for (companion in companionObjects) {
if (companion.name == "CREATOR") {
return companion
}
val creatorProperty = companion.declarations.asSequence()
.filterIsInstance<KtProperty>()
.firstOrNull { it.name == "CREATOR" }
?: continue
creatorProperty.findAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME) ?: continue
val initializer = creatorProperty.initializer ?: continue
when (initializer) {
is KtObjectLiteralExpression -> return initializer.objectDeclaration
is KtCallExpression -> {
val constructedClass = (initializer.resolveToCall()
?.resultingDescriptor as? ConstructorDescriptor)?.constructedClass
if (constructedClass != null) {
val sourceElement = constructedClass.source as? KotlinSourceElement
(sourceElement?.psi as? KtClassOrObject)?.let { return it }
}
}
}
}
return null
}
private fun KtNamedFunction.doesLookLikeCreateFromParcelOverride(): Boolean {
return name == "createFromParcel"
&& hasModifier(KtTokens.OVERRIDE_KEYWORD)
&& receiverTypeReference == null
&& valueParameters.size == 1
&& typeParameters.size == 0
&& valueParameters[0].typeReference?.getFqName() == ANDROID_PARCEL_CLASS_FQNAME.asString()
}
private fun findCreateFromParcel(creator: KtClassOrObject) = creator.findFunction { doesLookLikeCreateFromParcelOverride() }
private fun KtNamedFunction.doesLookLikeWriteImplementation(): Boolean {
val containingParcelableClassFqName = containingClassOrObject?.containingClass()?.fqName?.asString()
return name == PARCELER_WRITE_FUNCTION_NAME.asString()
&& hasModifier(KtTokens.OVERRIDE_KEYWORD)
&& receiverTypeReference?.getFqName() == containingParcelableClassFqName
&& valueParameters.size == 2
&& typeParameters.size == 0
&& valueParameters[0].typeReference?.getFqName() == ANDROID_PARCEL_CLASS_FQNAME.asString()
&& valueParameters[1].typeReference?.getFqName() == StandardNames.FqNames._int.asString()
}
private fun KtNamedFunction.doesLookLikeCreateImplementation(): Boolean {
return name == PARCELER_CREATE_FUNCTION_NAME.asString()
&& hasModifier(KtTokens.OVERRIDE_KEYWORD)
&& receiverTypeReference == null
&& valueParameters.size == 1
&& typeParameters.size == 0
&& valueParameters[0].typeReference?.getFqName() == ANDROID_PARCEL_CLASS_FQNAME.asString()
}
private fun KtObjectDeclaration.findCreateImplementation() = findFunction { doesLookLikeCreateImplementation() }
private fun KtObjectDeclaration.findWriteImplementation() = findFunction { doesLookLikeWriteImplementation() }
private fun KtClassOrObject.findFunction(f: KtNamedFunction.() -> Boolean) =
declarations.asSequence().filterIsInstance<KtNamedFunction>().firstOrNull(f)
private fun KtTypeReference.getFqName(): String? = analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, this]
?.constructor?.declarationDescriptor?.fqNameSafe?.asString()
}
object FactoryForWrite : AbstractFactory({ findElement<KtClass>()?.let { ParcelMigrateToParcelizeQuickFix(it) } })
object FactoryForCREATOR : AbstractFactory({
findElement<KtObjectDeclaration>()?.getStrictParentOfType<KtClass>()
?.let { ParcelMigrateToParcelizeQuickFix(it) }
})
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.migrate.to.parceler.companion.object")
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
override fun invoke(ktPsiFactory: KtPsiFactory, parcelableClass: KtClass) {
val parcelerObject = parcelableClass.findParcelerCompanionObject()?.first ?: parcelableClass.getOrCreateCompanionObject()
val bindingContext = parcelerObject.analyze(BodyResolveMode.PARTIAL)
val parcelerTypeArg = parcelableClass.name ?: run {
LOG.error("Parceler class should not be an anonymous class")
return
}
val parcelerObjectDescriptor = bindingContext[BindingContext.CLASS, parcelerObject] ?: run {
LOG.error("Unable to resolve parceler object for ${parcelableClass.name ?: "<unnamed Parcelable class>"}")
return
}
if (!parcelerObjectDescriptor.getAllSuperClassifiers().any { it.fqNameSafe == PARCELER_FQNAME }) {
val entryText = PARCELER_FQNAME.asString() + "<" + parcelerTypeArg + ">"
parcelerObject.addSuperTypeListEntry(ktPsiFactory.createSuperTypeEntry(entryText)).shortenReferences()
}
val oldWriteToParcelFunction = parcelableClass.findWriteToParcelOverride()
val oldCreateFromParcelFunction = parcelableClass.findCreatorClass()?.let { findCreateFromParcel(it) }
for (superTypeEntry in parcelerObject.superTypeListEntries) {
val superClass =
bindingContext[BindingContext.TYPE, superTypeEntry.typeReference]?.constructor?.declarationDescriptor ?: continue
if (superClass.getAllSuperClassifiers().any { it.fqNameSafe == ANDROID_PARCELABLE_CREATOR_CLASS_FQNAME }) {
parcelerObject.removeSuperTypeListEntry(superTypeEntry)
}
}
if (parcelerObject.name == "CREATOR") {
parcelerObject.nameIdentifier?.delete()
}
if (oldWriteToParcelFunction != null) {
parcelerObject.findWriteImplementation()?.delete() // Remove old implementation
val newFunction = oldWriteToParcelFunction.copy() as KtFunction
oldWriteToParcelFunction.delete()
newFunction.setName(PARCELER_WRITE_FUNCTION_NAME.asString())
newFunction.setModifierList(ktPsiFactory.createModifierList(KtTokens.OVERRIDE_KEYWORD))
newFunction.setReceiverTypeReference(ktPsiFactory.createType(parcelerTypeArg))
newFunction.valueParameterList?.apply {
assert(parameters.size == 2)
val parcelParameterName = parameters[0].name ?: "parcel"
val flagsParameterName = parameters[1].name ?: "flags"
repeat(parameters.size) { removeParameter(0) }
addParameter(ktPsiFactory.createParameter("$parcelParameterName : ${ANDROID_PARCEL_CLASS_FQNAME.asString()}"))
addParameter(ktPsiFactory.createParameter("$flagsParameterName : Int"))
}
parcelerObject.addDeclaration(newFunction).valueParameterList?.shortenReferences()
} else if (parcelerObject.findWriteImplementation() == null) {
val writeFunction = "fun $parcelerTypeArg.write(parcel: ${ANDROID_PARCEL_CLASS_FQNAME.asString()}, flags: Int) = TODO()"
parcelerObject.addDeclaration(ktPsiFactory.createFunction(writeFunction)).valueParameterList?.shortenReferences()
}
if (oldCreateFromParcelFunction != null) {
parcelerObject.findCreateImplementation()?.delete() // Remove old implementation
val newFunction = oldCreateFromParcelFunction.copy() as KtFunction
if (oldCreateFromParcelFunction.containingClassOrObject == parcelerObject) {
oldCreateFromParcelFunction.delete()
}
newFunction.setName(PARCELER_CREATE_FUNCTION_NAME.asString())
newFunction.setModifierList(ktPsiFactory.createModifierList(KtTokens.OVERRIDE_KEYWORD))
newFunction.setReceiverTypeReference(null)
newFunction.valueParameterList?.apply {
assert(parameters.size == 1)
val parcelParameterName = parameters[0].name ?: "parcel"
removeParameter(0)
addParameter(ktPsiFactory.createParameter("$parcelParameterName : ${ANDROID_PARCEL_CLASS_FQNAME.asString()}"))
}
parcelerObject.addDeclaration(newFunction).valueParameterList?.shortenReferences()
} else if (parcelerObject.findCreateImplementation() == null) {
val createFunction = "override fun create(parcel: ${ANDROID_PARCEL_CLASS_FQNAME.asString()}): $parcelerTypeArg = TODO()"
parcelerObject.addDeclaration(ktPsiFactory.createFunction(createFunction)).valueParameterList?.shortenReferences()
}
// Always use the default newArray() implementation
parcelerObject.findNewArrayOverride()?.delete()
parcelableClass.findDescribeContentsOverride()?.let { describeContentsFunction ->
val returnExpr = describeContentsFunction.bodyExpression?.unwrapBlockOrParenthesis()
if (returnExpr is KtReturnExpression && returnExpr.getTargetLabel() == null) {
val returnValue = returnExpr.analyze()[BindingContext.COMPILE_TIME_VALUE, returnExpr.returnedExpression]
?.getValue(TypeUtils.NO_EXPECTED_TYPE)
if (returnValue == 0) {
// There are no additional overrides in the hierarchy
if (bindingContext[BindingContext.FUNCTION, describeContentsFunction]?.overriddenDescriptors?.size == 1) {
describeContentsFunction.delete()
}
}
}
}
for (property in parcelerObject.declarations.asSequence().filterIsInstance<KtProperty>().filter { it.name == "CREATOR" }) {
if (property.findAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME) != null) {
property.delete()
}
}
}
}
@@ -0,0 +1,35 @@
/*
* 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.parcelize.ide.quickfixes
import org.jetbrains.kotlin.parcelize.ide.KotlinParcelizeBundle
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPsiFactory
class ParcelRemoveCustomCreatorProperty(property: KtProperty) : AbstractParcelizeQuickFix<KtProperty>(property) {
object Factory : AbstractFactory(f@ {
// KtProperty or its name identifier
psiElement as? KtProperty ?: (psiElement.parent as? KtProperty) ?: return@f null
findElement<KtProperty>()?.let(::ParcelRemoveCustomCreatorProperty)
})
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.remove.custom.creator.property")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtProperty) {
element.delete()
}
}
@@ -0,0 +1,31 @@
/*
* 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.parcelize.ide.quickfixes
import org.jetbrains.kotlin.parcelize.ide.KotlinParcelizeBundle
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtPsiFactory
class ParcelRemoveCustomWriteToParcel(function: KtFunction) : AbstractParcelizeQuickFix<KtFunction>(function) {
object Factory : AbstractFactory({ findElement<KtFunction>()?.let(::ParcelRemoveCustomWriteToParcel) })
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.remove.custom.write.to.parcel.function")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtFunction) {
element.delete()
}
}
@@ -0,0 +1,32 @@
/*
* 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.parcelize.ide.quickfixes
import kotlinx.parcelize.IgnoredOnParcel
import org.jetbrains.kotlin.parcelize.ide.KotlinParcelizeBundle
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPsiFactory
class ParcelizeAddIgnoreOnParcelAnnotationQuickFix(property: KtProperty) : AbstractParcelizeQuickFix<KtProperty>(property) {
object Factory : AbstractFactory({ findElement<KtProperty>()?.let(::ParcelizeAddIgnoreOnParcelAnnotationQuickFix) })
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.add.ignored.on.parcel.annotation")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtProperty) {
element.addAnnotationEntry(ktPsiFactory.createAnnotationEntry("@" + IgnoredOnParcel::class.java.name)).shortenReferences()
}
}
@@ -0,0 +1,40 @@
/*
* 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.parcelize.ide.quickfixes
import org.jetbrains.kotlin.parcelize.ide.KotlinParcelizeBundle
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.createPrimaryConstructorIfAbsent
class ParcelizeAddPrimaryConstructorQuickFix(clazz: KtClass) : AbstractParcelizeQuickFix<KtClass>(clazz) {
object Factory : AbstractFactory({ findElement<KtClass>()?.let(::ParcelizeAddPrimaryConstructorQuickFix) })
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.add.empty.primary.constructor")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtClass) {
element.createPrimaryConstructorIfAbsent()
for (secondaryConstructor in element.secondaryConstructors) {
if (secondaryConstructor.getDelegationCall().isImplicit) {
val parameterList = secondaryConstructor.valueParameterList ?: return
val colon = secondaryConstructor.addAfter(ktPsiFactory.createColon(), parameterList)
secondaryConstructor.addAfter(ktPsiFactory.createExpression("this()"), colon)
}
}
}
}
@@ -0,0 +1,32 @@
/*
* 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.parcelize.ide.quickfixes
import org.jetbrains.kotlin.parcelize.ANDROID_PARCELABLE_CLASS_FQNAME
import org.jetbrains.kotlin.parcelize.ide.KotlinParcelizeBundle
import org.jetbrains.kotlin.psi.*
class ParcelizeAddSupertypeQuickFix(clazz: KtClassOrObject) : AbstractParcelizeQuickFix<KtClassOrObject>(clazz) {
object Factory : AbstractFactory({ findElement<KtClassOrObject>()?.let(::ParcelizeAddSupertypeQuickFix) })
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.add.parcelable.supertype")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtClassOrObject) {
val supertypeName = ANDROID_PARCELABLE_CLASS_FQNAME.asString()
element.addSuperTypeListEntry(ktPsiFactory.createSuperTypeEntry(supertypeName)).shortenReferences()
}
}
@@ -0,0 +1,45 @@
/*
* 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.parcelize.ide.quickfixes
import org.jetbrains.kotlin.idea.quickfix.QuickFixContributor
import org.jetbrains.kotlin.idea.quickfix.QuickFixes
import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.parcelize.diagnostic.ErrorsParcelize
class ParcelizeQuickFixContributor : QuickFixContributor {
override fun registerQuickFixes(quickFixes: QuickFixes) {
quickFixes.register(
ErrorsParcelize.PARCELABLE_CANT_BE_INNER_CLASS,
RemoveModifierFix.createRemoveModifierFromListOwnerFactory(KtTokens.INNER_KEYWORD, false)
)
quickFixes.register(ErrorsParcelize.NO_PARCELABLE_SUPERTYPE, ParcelizeAddSupertypeQuickFix.Factory)
quickFixes.register(ErrorsParcelize.PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR, ParcelizeAddPrimaryConstructorQuickFix.Factory)
quickFixes.register(ErrorsParcelize.PROPERTY_WONT_BE_SERIALIZED, ParcelizeAddIgnoreOnParcelAnnotationQuickFix.Factory)
quickFixes.register(ErrorsParcelize.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED, ParcelMigrateToParcelizeQuickFix.FactoryForWrite)
quickFixes.register(ErrorsParcelize.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED, ParcelRemoveCustomWriteToParcel.Factory)
quickFixes.register(ErrorsParcelize.CREATOR_DEFINITION_IS_NOT_ALLOWED, ParcelMigrateToParcelizeQuickFix.FactoryForCREATOR)
quickFixes.register(ErrorsParcelize.CREATOR_DEFINITION_IS_NOT_ALLOWED, ParcelRemoveCustomCreatorProperty.Factory)
quickFixes.register(ErrorsParcelize.REDUNDANT_TYPE_PARCELER, ParcelizeRemoveDuplicatingTypeParcelerAnnotationQuickFix.Factory)
quickFixes.register(ErrorsParcelize.CLASS_SHOULD_BE_PARCELIZE, AnnotateWithParcelizeQuickFix.Factory)
}
}
@@ -0,0 +1,31 @@
/*
* 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.parcelize.ide.quickfixes
import org.jetbrains.kotlin.parcelize.ide.KotlinParcelizeBundle
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtPsiFactory
class ParcelizeRemoveDuplicatingTypeParcelerAnnotationQuickFix(anno: KtAnnotationEntry) : AbstractParcelizeQuickFix<KtAnnotationEntry>(anno) {
object Factory : AbstractFactory({ findElement<KtAnnotationEntry>()?.let(::ParcelizeRemoveDuplicatingTypeParcelerAnnotationQuickFix) })
override fun getText() = KotlinParcelizeBundle.message("parcelize.fix.remove.redundant.type.parceler.annotation")
override fun invoke(ktPsiFactory: KtPsiFactory, element: KtAnnotationEntry) {
element.delete()
}
}
@@ -0,0 +1,29 @@
// WITH_RUNTIME
package test
import kotlinx.parcelize.Parcelize
import android.os.Parcelable
@Parcelize
class A : Parcelable
@Parcelize
class B(val firstName: String, val secondName: String) : Parcelable
@Parcelize
class C(val firstName: String, <error descr="[PARCELABLE_CONSTRUCTOR_PARAMETER_SHOULD_BE_VAL_OR_VAR] 'Parcelable' constructor parameter should be 'val' or 'var'">secondName</error>: String) : Parcelable
@Parcelize
class D(val firstName: String, vararg val secondName: String) : Parcelable
@Parcelize
class E(val firstName: String, val secondName: String) : Parcelable {
constructor() : this("", "")
}
@Parcelize
class <error descr="[PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR] 'Parcelable' should have a primary constructor">F</error> : Parcelable {
constructor(a: String) {
println(a)
}
}
@@ -0,0 +1,25 @@
// WITH_RUNTIME
package test
import kotlinx.parcelize.Parcelize
import android.os.Parcelable
import android.os.Parcel
@Parcelize
class A(val a: String) : Parcelable {
companion object {
@JvmField
val <error descr="[CREATOR_DEFINITION_IS_NOT_ALLOWED] 'CREATOR' definition is not allowed. Use 'Parceler' companion object instead">CREATOR</error> = object : Parcelable.Creator<A> {
override fun createFromParcel(source: Parcel): A = A("")
override fun newArray(size: Int) = arrayOfNulls<A>(size)
}
}
}
@Parcelize
class B(val b: String) : Parcelable {
companion object <error descr="[CREATOR_DEFINITION_IS_NOT_ALLOWED] 'CREATOR' definition is not allowed. Use 'Parceler' companion object instead">CREATOR</error> : Parcelable.Creator<B> {
override fun createFromParcel(source: Parcel): B = B("")
override fun newArray(size: Int) = arrayOfNulls<B>(size)
}
}
@@ -0,0 +1,45 @@
// WITH_RUNTIME
package test
import kotlinx.parcelize.*
import android.os.*
object StringParceler : Parceler<String> {
override fun create(parcel: Parcel) = TODO()
override fun String.write(parcel: Parcel, flags: Int) = TODO()
}
object CharSequenceParceler : Parceler<CharSequence> {
override fun create(parcel: Parcel) = TODO()
override fun CharSequence.write(parcel: Parcel, flags: Int) = TODO()
}
class StringClassParceler : Parceler<String> {
override fun create(parcel: Parcel) = TODO()
override fun String.write(parcel: Parcel, flags: Int) = TODO()
}
@<error descr="[CLASS_SHOULD_BE_PARCELIZE] Class 'MissingParcelizeAnnotation' should be annotated with '@Parcelize'">TypeParceler</error><String, StringParceler>
class MissingParcelizeAnnotation(val a: @WriteWith<StringParceler> String)
@Parcelize
@TypeParceler<String, StringClassParceler>
class ShouldBeClass(val a: @WriteWith<StringClassParceler> String) : Parcelable
@Parcelize
class Test(
val a: @WriteWith<StringParceler> Int,
val b: @WriteWith<StringParceler> String,
val c: @WriteWith<<error descr="[PARCELER_TYPE_INCOMPATIBLE] Parceler type String is incompatible with CharSequence">StringParceler</error>> CharSequence,
val d: @WriteWith<CharSequenceParceler> String,
val e: @WriteWith<CharSequenceParceler> CharSequence
) : Parcelable
@Parcelize
@TypeParceler<String, StringParceler>
class Test2(@<warning descr="[REDUNDANT_TYPE_PARCELER] This 'TypeParceler' is already provided for Class 'Test2'">TypeParceler</warning><String, StringParceler> val a: String) : Parcelable
@Parcelize
@TypeParceler<<error descr="[DUPLICATING_TYPE_PARCELERS] Duplicating ''TypeParceler'' annotations">String</error>, StringParceler>
@TypeParceler<<error descr="[DUPLICATING_TYPE_PARCELERS] Duplicating ''TypeParceler'' annotations">String</error>, CharSequenceParceler>
class Test3(val a: String) : Parcelable
@@ -0,0 +1,21 @@
package test
import kotlinx.parcelize.Parcelize
import android.os.Parcelable
import android.os.Parcel
@Parcelize
class A(val a: String) : Parcelable {
<error descr="[OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED] Overriding 'writeToParcel' is not allowed. Use 'Parceler' companion object instead">override</error> fun writeToParcel(p: Parcel?, flags: Int) {}
override fun describeContents() = 0
}
@Parcelize
class B(val a: String) : Parcelable {
<error descr="[OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED] Overriding 'writeToParcel' is not allowed. Use 'Parceler' companion object instead">override</error> fun writeToParcel(p: Parcel?, flags: Int) {}
}
@Parcelize
class C(val a: String) : Parcelable {
<error descr="[OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED] Overriding 'writeToParcel' is not allowed. Use 'Parceler' companion object instead">override</error> fun writeToParcel(p: Parcel, flags: Int) {}
}
@@ -0,0 +1,13 @@
package test
import kotlinx.parcelize.Parcelize
import android.os.Parcelable
import android.os.Parcel
open class Delegate : Parcelable {
override fun writeToParcel(dest: Parcel?, flags: Int) {}
override fun describeContents() = 0
}
@Parcelize
class Test : Parcelable <error descr="[PARCELABLE_DELEGATE_IS_NOT_ALLOWED] Delegating 'Parcelable' is not allowed">by</error> Delegate()
@@ -0,0 +1,10 @@
package test
import kotlinx.parcelize.Parcelize
import android.os.Parcelable
@Parcelize
class User : Parcelable
@Parcelize
class <warning descr="[PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY] The primary constructor is empty, no data will be serialized to 'Parcel'">User2</warning>() : Parcelable
@@ -0,0 +1,20 @@
package test
import kotlinx.parcelize.*
import android.os.*
class Box(val value: String)
@Parcelize
class Foo(val box: Box): Parcelable {
companion object : Parceler<Foo> {
override fun create(parcel: Parcel) = Foo(Box(parcel.readString()))
override fun Foo.write(parcel: Parcel, flags: Int) {
parcel.writeString(box.value)
}
}
}
@Parcelize
class Foo2(val box: <error descr="[PARCELABLE_TYPE_NOT_SUPPORTED] Type is not directly supported by 'Parcelize'. Annotate the parameter type with '@RawValue' if you want it to be serialized using 'writeValue()'">Box</error>): Parcelable
@@ -0,0 +1,31 @@
package test
import kotlinx.parcelize.Parcelize
import android.os.Parcelable
@Parcelize
open class Open(val foo: String) : Parcelable
@Parcelize
class Final(val foo: String) : Parcelable
@Parcelize
<error descr="[PARCELABLE_SHOULD_BE_INSTANTIABLE] 'Parcelable' should not be a 'sealed' or 'abstract' class">abstract</error> class Abstract(val foo: String) : Parcelable
@Parcelize
<error descr="[PARCELABLE_SHOULD_BE_INSTANTIABLE] 'Parcelable' should not be a 'sealed' or 'abstract' class">sealed</error> class Sealed(val foo: String) : Parcelable {
class X : Sealed("")
}
class Outer {
@Parcelize
<error descr="[PARCELABLE_CANT_BE_INNER_CLASS] 'Parcelable' can't be an inner class">inner</error> class Inner(val foo: String) : Parcelable
}
fun foo() {
@Parcelize
<error descr="[PARCELABLE_CANT_BE_LOCAL_CLASS] 'Parcelable' can't be a local class">object</error> : Parcelable {}
@Parcelize
class <error descr="[PARCELABLE_CANT_BE_LOCAL_CLASS] 'Parcelable' can't be a local class"><error descr="[NO_PARCELABLE_SUPERTYPE] No 'Parcelable' supertype">Local</error></error> {}
}
@@ -0,0 +1,11 @@
package test
import kotlinx.parcelize.Parcelize
import android.os.Parcel
import android.os.Parcelable
@Suppress("UNUSED_PARAMETER")
class User(firstName: String, secondName: String, val age: Int) : Parcelable {
override fun writeToParcel(p0: Parcel?, p1: Int) {}
override fun describeContents() = 0
}
@@ -0,0 +1,37 @@
// WITH_RUNTIME
package test
import kotlinx.parcelize.*
import android.os.Parcelable
@Parcelize
class A(val firstName: String) : Parcelable {
val <warning descr="[PROPERTY_WONT_BE_SERIALIZED] Property would not be serialized into a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove the warning">secondName</warning>: String = ""
val <warning descr="[PROPERTY_WONT_BE_SERIALIZED] Property would not be serialized into a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove the warning">delegated</warning> by lazy { "" }
lateinit var <warning descr="[PROPERTY_WONT_BE_SERIALIZED] Property would not be serialized into a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove the warning">lateinit</warning>: String
val customGetter: String
get() = ""
var customSetter: String
get() = ""
set(<warning descr="[UNUSED_PARAMETER] Parameter 'v' is never used">v</warning>) {}
}
@Parcelize
@Suppress("WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET")
class B(<warning descr="[INAPPLICABLE_IGNORED_ON_PARCEL_CONSTRUCTOR_PROPERTY] '@IgnoredOnParcel' is inapplicable to properties declared in the primary constructor">@IgnoredOnParcel</warning> val firstName: String) : Parcelable {
@IgnoredOnParcel
var a: String = ""
@field:IgnoredOnParcel
var <warning descr="[PROPERTY_WONT_BE_SERIALIZED] Property would not be serialized into a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove the warning">b</warning>: String = ""
@get:IgnoredOnParcel
var c: String = ""
@set:IgnoredOnParcel
var <warning descr="[PROPERTY_WONT_BE_SERIALIZED] Property would not be serialized into a 'Parcel'. Add '@IgnoredOnParcel' annotation to remove the warning">d</warning>: String = ""
}
@@ -0,0 +1,7 @@
package test
import kotlinx.parcelize.Parcelize
import android.os.Parcelable
@Parcelize
class User(val firstName: String, val secondName: String, val age: Int) : Parcelable
@@ -0,0 +1,17 @@
package test
import kotlinx.parcelize.Parcelize
import kotlinx.parcelize.RawValue
import android.os.Parcelable
@Parcelize
class User(
val a: String,
val b: <error descr="[PARCELABLE_TYPE_NOT_SUPPORTED] Type is not directly supported by 'Parcelize'. Annotate the parameter type with '@RawValue' if you want it to be serialized using 'writeValue()'">Any</error>,
val c: <error descr="[PARCELABLE_TYPE_NOT_SUPPORTED] Type is not directly supported by 'Parcelize'. Annotate the parameter type with '@RawValue' if you want it to be serialized using 'writeValue()'">Any?</error>,
val d: <error descr="[PARCELABLE_TYPE_NOT_SUPPORTED] Type is not directly supported by 'Parcelize'. Annotate the parameter type with '@RawValue' if you want it to be serialized using 'writeValue()'">Map<Any, String></error>,
val e: @RawValue Any?,
val f: @RawValue Map<String, Any>,
val g: Map<String, @RawValue Any>,
val h: Map<@RawValue Any, List<@RawValue Any>>
) : Parcelable
@@ -0,0 +1,20 @@
package test
import kotlinx.parcelize.Parcelize
import android.os.Parcelable
@Parcelize
class <error descr="[NO_PARCELABLE_SUPERTYPE] No 'Parcelable' supertype">Without</error>(val firstName: String, val secondName: String, val age: Int)
@Parcelize
class With(val firstName: String, val secondName: String, val age: Int) : Parcelable
interface MyParcelableIntf : Parcelable
abstract class MyParcelableCl : Parcelable
@Parcelize
class WithIntfSubtype(val firstName: String, val secondName: String, val age: Int) : MyParcelableIntf
@Parcelize
class WithClSubtype(val firstName: String, val secondName: String, val age: Int) : MyParcelableCl()
@@ -0,0 +1,25 @@
package test
import kotlinx.parcelize.Parcelize
import android.os.Parcelable
@Parcelize
interface <error descr="[PARCELABLE_SHOULD_BE_CLASS] 'Parcelable' should be a class">Intf</error> : Parcelable
@Parcelize
object <error descr="[NO_PARCELABLE_SUPERTYPE] No 'Parcelable' supertype">Obj</error>
class A {
@Parcelize
companion <error descr="[NO_PARCELABLE_SUPERTYPE] No 'Parcelable' supertype">object</error> {
fun foo() {}
}
}
@Parcelize
enum class <error descr="[NO_PARCELABLE_SUPERTYPE] No 'Parcelable' supertype">Enum</error> {
WHITE, BLACK
}
@Parcelize
annotation class <error descr="[PARCELABLE_SHOULD_BE_CLASS] 'Parcelable' should be a class">Anno</error>
@@ -0,0 +1,13 @@
// "Add empty primary constructor" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
class <caret>Test : Parcelable {
constructor(s: String)
constructor(s: String, i: Int) : this(s)
}
@@ -0,0 +1,13 @@
// "Add empty primary constructor" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
class <caret>Test() : Parcelable {
constructor(s: String) : this()
constructor(s: String, i: Int) : this(s)
}
@@ -0,0 +1,11 @@
// "Add empty primary constructor" "false"
// IGNORE_IRRELEVANT_ACTIONS
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
class <caret>Test() : Parcelable
@@ -0,0 +1,12 @@
// "Add empty primary constructor" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
class <caret>Test : Parcelable {
constructor(a: Int)
}
@@ -0,0 +1,12 @@
// "Add empty primary constructor" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
class <caret>Test() : Parcelable {
constructor(a: Int) : this()
}
@@ -0,0 +1,12 @@
// "Remove 'inner' modifier" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
class Foo {
@Parcelize
<caret>inner class Bar : Parcelable
}
@@ -0,0 +1,12 @@
// "Remove 'inner' modifier" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
class Foo {
@Parcelize<caret>
class Bar : Parcelable
}
@@ -0,0 +1,15 @@
// "Annotate containing class with ''@Parcelize''" "true"
// ERROR: No 'Parcelable' supertype
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.*
object StringParceler : Parceler<String> {
override fun create(parcel: Parcel) = TODO()
override fun String.write(parcel: Parcel, flags: Int) = TODO()
}
class Foo(@<caret>TypeParceler<String, StringParceler> val a: String)
@@ -0,0 +1,16 @@
// "Annotate containing class with ''@Parcelize''" "true"
// ERROR: No 'Parcelable' supertype
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.*
object StringParceler : Parceler<String> {
override fun create(parcel: Parcel) = TODO()
override fun String.write(parcel: Parcel, flags: Int) = TODO()
}
@Parcelize
class Foo(@<caret>TypeParceler<String, StringParceler> val a: String)
@@ -0,0 +1,36 @@
// "Remove custom ''CREATOR'' property" "true"
// ERROR: Overriding 'writeToParcel' is not allowed. Use 'Parceler' companion object instead
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val a: String) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString()) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(a)
}
override fun describeContents(): Int {
return 0
}
companion object {
@JvmField
val <caret>CREATOR = object : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
}
@@ -0,0 +1,26 @@
// "Remove custom ''CREATOR'' property" "true"
// ERROR: Overriding 'writeToParcel' is not allowed. Use 'Parceler' companion object instead
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val a: String) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString()) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(a)
}
override fun describeContents(): Int {
return 0
}
companion object {
<caret>}
}
@@ -0,0 +1,33 @@
// "Remove custom ''writeToParcel()'' function" "true"
// ERROR: 'CREATOR' definition is not allowed. Use 'Parceler' companion object instead
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val a: String) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString()) {
}
<caret>override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(a)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
@@ -0,0 +1,29 @@
// "Remove custom ''writeToParcel()'' function" "true"
// ERROR: 'CREATOR' definition is not allowed. Use 'Parceler' companion object instead
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val a: String) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString()) {
}
<caret>override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
@@ -0,0 +1,34 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readInt()) {
}
<caret>override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
@@ -0,0 +1,28 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readInt()) {
}
<caret>companion object : Parceler<Foo> {
override fun Foo.write(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
override fun create(parcel: Parcel): Foo {
return Foo(parcel)
}
}
}
@@ -0,0 +1,32 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString(), parcel.readInt())
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
companion object {
@JvmField
val <caret>CREATOR: Parcelable.Creator<Foo> = object : Creator() {}
}
private abstract class Creator : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
@@ -0,0 +1,32 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString(), parcel.readInt())
companion object : Parceler<Foo> {
<caret>override fun Foo.write(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
override fun create(parcel: Parcel): Foo = TODO()
}
private abstract class Creator : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
@@ -0,0 +1,34 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readInt()) {
}
<caret>override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
override fun describeContents(): Int {
return 50
}
companion object CREATOR : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
@@ -0,0 +1,32 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readInt()) {
}
<caret>override fun describeContents(): Int {
return 50
}
companion object : Parceler<Foo> {
override fun Foo.write(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
override fun create(parcel: Parcel): Foo {
return Foo(parcel)
}
}
}
@@ -0,0 +1,30 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readInt()) {
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
companion object <caret>CREATOR : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
@@ -0,0 +1,28 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readInt()) {
}
companion object <caret>: Parceler<Foo> {
override fun Foo.write(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
override fun create(parcel: Parcel): Foo {
return Foo(parcel)
}
}
}
@@ -0,0 +1,32 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString(), parcel.readInt())
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
companion object {
@JvmField
val <caret>CREATOR: Parcelable.Creator<Foo> = Creator()
}
private class Creator : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
@@ -0,0 +1,34 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString(), parcel.readInt())
companion object : Parceler<Foo> {
<caret>override fun Foo.write(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
override fun create(parcel: Parcel): Foo {
return Foo(parcel)
}
}
private class Creator : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
@@ -0,0 +1,30 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString(), parcel.readInt())
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
companion object {
@JvmField
val <caret>CREATOR = object : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
}
@@ -0,0 +1,24 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString(), parcel.readInt())
companion object : Parceler<Foo> {
<caret>override fun Foo.write(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
override fun create(parcel: Parcel): Foo {
return Foo(parcel)
}
}
}
@@ -0,0 +1,30 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readInt()) {
}
<caret>override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
companion object CREATOR : Parcelable.Creator<Foo> {
override fun createFromParcel(parcel: Parcel): Foo {
return Foo(parcel)
}
override fun newArray(size: Int): Array<Foo?> {
return arrayOfNulls(size)
}
}
}
@@ -0,0 +1,28 @@
// "Migrate to ''Parceler'' companion object" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize
@Parcelize
class Foo(val firstName: String, val age: Int) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readInt()) {
}
<caret>companion object : Parceler<Foo> {
override fun Foo.write(parcel: Parcel, flags: Int) {
parcel.writeString(firstName)
parcel.writeInt(age)
}
override fun create(parcel: Parcel): Foo {
return Foo(parcel)
}
}
}
@@ -0,0 +1,13 @@
// "Add ''Parcelable'' supertype" "false"
// IGNORE_IRRELEVANT_ACTIONS
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
abstract class AbstractParcelable : Parcelable
@Parcelize
class <caret>Test(val s: String) : AbstractParcelable()
@@ -0,0 +1,10 @@
// "Add ''Parcelable'' supertype" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
class <caret>Test(val s: String)
@@ -0,0 +1,10 @@
// "Add ''Parcelable'' supertype" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
class <caret>Test(val s: String) : Parcelable
@@ -0,0 +1,12 @@
// "Add ''@IgnoredOnParcel'' annotation" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
class Test : Parcelable {
val <caret>a = 5
}
@@ -0,0 +1,14 @@
// "Add ''@IgnoredOnParcel'' annotation" "true"
// WITH_RUNTIME
package com.myapp.activity
import android.os.Parcelable
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
@Parcelize
class Test : Parcelable {
@IgnoredOnParcel
val <caret>a = 5
}
@@ -0,0 +1,17 @@
// "Remove redundant ''@TypeParceler'' annotation" "true"
// WARNING: This annotation duplicates the one for Class 'Foo'
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.*
object StringParceler : Parceler<String> {
override fun create(parcel: Parcel) = TODO()
override fun String.write(parcel: Parcel, flags: Int) = TODO()
}
@Parcelize
@TypeParceler<String, StringParceler>
class Foo(@<caret>TypeParceler<String, StringParceler> val a: String) : Parcelable
@@ -0,0 +1,17 @@
// "Remove redundant ''@TypeParceler'' annotation" "true"
// WARNING: This annotation duplicates the one for Class 'Foo'
// WITH_RUNTIME
package com.myapp.activity
import android.os.*
import kotlinx.parcelize.*
object StringParceler : Parceler<String> {
override fun create(parcel: Parcel) = TODO()
override fun String.write(parcel: Parcel, flags: Int) = TODO()
}
@Parcelize
@TypeParceler<String, StringParceler>
class Foo(<caret>val a: String) : Parcelable
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2020 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.pacelize.ide.test
import org.jetbrains.kotlin.checkers.AbstractPsiCheckerTest
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.test.KotlinTestUtils
abstract class AbstractParcelizeCheckerTest : AbstractPsiCheckerTest() {
override fun setUp() {
super.setUp()
val androidJar = KotlinTestUtils.findAndroidApiJar()
ConfigLibraryUtil.addLibrary(module, "androidJar", androidJar.parentFile.absolutePath, arrayOf(androidJar.name))
ConfigLibraryUtil.addLibrary(module, "androidExtensionsRuntime", "dist/kotlinc/lib", arrayOf("parcelize-runtime.jar"))
}
override fun tearDown() {
ConfigLibraryUtil.removeLibrary(module, "androidJar")
ConfigLibraryUtil.removeLibrary(module, "androidExtensionsRuntime")
super.tearDown()
}
}
@@ -0,0 +1,38 @@
/*
* 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.pacelize.ide.test
import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixTest
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.test.KotlinTestUtils
abstract class AbstractParcelizeQuickFixTest : AbstractQuickFixTest() {
override fun setUp() {
super.setUp()
val androidJar = KotlinTestUtils.findAndroidApiJar()
ConfigLibraryUtil.addLibrary(module, "androidJar", androidJar.parentFile.absolutePath, arrayOf(androidJar.name))
ConfigLibraryUtil.addLibrary(module, "androidExtensionsRuntime", "dist/kotlinc/lib", arrayOf("parcelize-runtime.jar"))
}
override fun tearDown() {
ConfigLibraryUtil.removeLibrary(module, "androidJar")
ConfigLibraryUtil.removeLibrary(module, "androidExtensionsRuntime")
super.tearDown()
}
}
@@ -0,0 +1,100 @@
/*
* Copyright 2010-2020 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.pacelize.ide.test;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("plugins/parcelize/parcelize-ide/testData/checker")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class ParcelizeCheckerTestGenerated extends AbstractParcelizeCheckerTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInChecker() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-ide/testData/checker"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@TestMetadata("constructors.kt")
public void testConstructors() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/constructors.kt");
}
@TestMetadata("customCreator.kt")
public void testCustomCreator() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/customCreator.kt");
}
@TestMetadata("customParcelers.kt")
public void testCustomParcelers() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/customParcelers.kt");
}
@TestMetadata("customWriteToParcel.kt")
public void testCustomWriteToParcel() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/customWriteToParcel.kt");
}
@TestMetadata("delegate.kt")
public void testDelegate() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/delegate.kt");
}
@TestMetadata("emptyPrimaryConstructor.kt")
public void testEmptyPrimaryConstructor() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/emptyPrimaryConstructor.kt");
}
@TestMetadata("kt20062.kt")
public void testKt20062() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/kt20062.kt");
}
@TestMetadata("modality.kt")
public void testModality() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/modality.kt");
}
@TestMetadata("notMagicParcel.kt")
public void testNotMagicParcel() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/notMagicParcel.kt");
}
@TestMetadata("properties.kt")
public void testProperties() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/properties.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/simple.kt");
}
@TestMetadata("unsupportedType.kt")
public void testUnsupportedType() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/unsupportedType.kt");
}
@TestMetadata("withoutParcelableSupertype.kt")
public void testWithoutParcelableSupertype() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/withoutParcelableSupertype.kt");
}
@TestMetadata("wrongAnnotationTarget.kt")
public void testWrongAnnotationTarget() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/checker/wrongAnnotationTarget.kt");
}
}
@@ -0,0 +1,224 @@
/*
* Copyright 2010-2020 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.pacelize.ide.test;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("plugins/parcelize/parcelize-ide/testData/quickfix")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class ParcelizeQuickFixTestGenerated extends AbstractParcelizeQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInQuickfix() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-ide/testData/quickfix"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("plugins/parcelize/parcelize-ide/testData/quickfix/addPrimaryConstructor")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class AddPrimaryConstructor extends AbstractParcelizeQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInAddPrimaryConstructor() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-ide/testData/quickfix/addPrimaryConstructor"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("constructorWithDelegate.kt")
public void testConstructorWithDelegate() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/addPrimaryConstructor/constructorWithDelegate.kt");
}
@TestMetadata("noQuickFix.kt")
public void testNoQuickFix() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/addPrimaryConstructor/noQuickFix.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/addPrimaryConstructor/simple.kt");
}
}
@TestMetadata("plugins/parcelize/parcelize-ide/testData/quickfix/cantBeInnerClass")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class CantBeInnerClass extends AbstractParcelizeQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInCantBeInnerClass() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-ide/testData/quickfix/cantBeInnerClass"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/cantBeInnerClass/simple.kt");
}
}
@TestMetadata("plugins/parcelize/parcelize-ide/testData/quickfix/classShouldBeAnnotated")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClassShouldBeAnnotated extends AbstractParcelizeQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInClassShouldBeAnnotated() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-ide/testData/quickfix/classShouldBeAnnotated"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/classShouldBeAnnotated/simple.kt");
}
}
@TestMetadata("plugins/parcelize/parcelize-ide/testData/quickfix/deleteIncompatible")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DeleteIncompatible extends AbstractParcelizeQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInDeleteIncompatible() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-ide/testData/quickfix/deleteIncompatible"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("creatorField.kt")
public void testCreatorField() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/deleteIncompatible/creatorField.kt");
}
@TestMetadata("writeToParcel.kt")
public void testWriteToParcel() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/deleteIncompatible/writeToParcel.kt");
}
}
@TestMetadata("plugins/parcelize/parcelize-ide/testData/quickfix/migrations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Migrations extends AbstractParcelizeQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInMigrations() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-ide/testData/quickfix/migrations"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("basic.kt")
public void testBasic() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/migrations/basic.kt");
}
@TestMetadata("complexCase1.kt")
public void testComplexCase1() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/migrations/complexCase1.kt");
}
@TestMetadata("customDescribeContents.kt")
public void testCustomDescribeContents() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/migrations/customDescribeContents.kt");
}
@TestMetadata("fromCreatorObject.kt")
public void testFromCreatorObject() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/migrations/fromCreatorObject.kt");
}
@TestMetadata("innerClassFactory.kt")
public void testInnerClassFactory() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/migrations/innerClassFactory.kt");
}
@TestMetadata("jvmField.kt")
public void testJvmField() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/migrations/jvmField.kt");
}
@TestMetadata("withoutDescribeContents.kt")
public void testWithoutDescribeContents() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/migrations/withoutDescribeContents.kt");
}
}
@TestMetadata("plugins/parcelize/parcelize-ide/testData/quickfix/noParcelableSupertype")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NoParcelableSupertype extends AbstractParcelizeQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInNoParcelableSupertype() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-ide/testData/quickfix/noParcelableSupertype"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("alreadyHasSupertype.kt")
public void testAlreadyHasSupertype() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/noParcelableSupertype/alreadyHasSupertype.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/noParcelableSupertype/simple.kt");
}
}
@TestMetadata("plugins/parcelize/parcelize-ide/testData/quickfix/propertyWontBeSerialized")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PropertyWontBeSerialized extends AbstractParcelizeQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInPropertyWontBeSerialized() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-ide/testData/quickfix/propertyWontBeSerialized"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/propertyWontBeSerialized/simple.kt");
}
}
@TestMetadata("plugins/parcelize/parcelize-ide/testData/quickfix/removeDuplicatingTypeParcelerAnnotation")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class RemoveDuplicatingTypeParcelerAnnotation extends AbstractParcelizeQuickFixTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInRemoveDuplicatingTypeParcelerAnnotation() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-ide/testData/quickfix/removeDuplicatingTypeParcelerAnnotation"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), null, true);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("plugins/parcelize/parcelize-ide/testData/quickfix/removeDuplicatingTypeParcelerAnnotation/simple.kt");
}
}
}
+2
View File
@@ -140,6 +140,7 @@ val libraryProjects = listOf(
":kotlin-noarg-compiler-plugin",
":kotlin-sam-with-receiver-compiler-plugin",
":plugins:android-extensions-compiler",
":plugins:parcelize:parcelize-compiler",
":kotlinx-serialization-compiler-plugin",
":idea:ide-common"
)
@@ -192,6 +193,7 @@ dependencies {
gradleToolingModel(project(":sam-with-receiver-ide-plugin")) { isTransitive = false }
gradleToolingModel(project(":plugins:kapt3-idea")) { isTransitive = false }
gradleToolingModel(project(":plugins:android-extensions-ide")) { isTransitive = false }
gradleToolingModel(project(":plugins:parcelize:parcelize-ide")) { isTransitive = false }
gradleToolingModel(project(":noarg-ide-plugin")) { isTransitive = false }
gradleToolingModel(project(":allopen-ide-plugin")) { isTransitive = false }
+1
View File
@@ -324,6 +324,7 @@ include ":compiler:fir:cones",
include ":idea:idea-frontend-fir:idea-fir-low-level-api"
include ":plugins:parcelize:parcelize-compiler",
":plugins:parcelize:parcelize-ide",
":plugins:parcelize:parcelize-runtime",
":kotlin-parcelize-compiler"