Add intentions Add/Remove/Redo parcelable implementation
#KT-17465 Fixed #KT-12049 Fixed
This commit is contained in:
@@ -1040,6 +1040,10 @@ public abstract class KotlinBuiltIns {
|
||||
return descriptor.getContainingDeclaration() == getAny();
|
||||
}
|
||||
|
||||
public static boolean isCharSequence(@Nullable KotlinType type) {
|
||||
return type != null && isNotNullConstructedFromGivenClass(type, FQ_NAMES.charSequence);
|
||||
}
|
||||
|
||||
public static boolean isString(@Nullable KotlinType type) {
|
||||
return type != null && isNotNullConstructedFromGivenClass(type, FQ_NAMES.string);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.allopen.AbstractBytecodeListingTestForAllOpen
|
||||
import org.jetbrains.kotlin.android.*
|
||||
import org.jetbrains.kotlin.android.configure.AbstractConfigureProjectTest
|
||||
import org.jetbrains.kotlin.android.folding.AbstractAndroidResourceFoldingTest
|
||||
import org.jetbrains.kotlin.android.intention.AbstractAndroidIntentionTest
|
||||
import org.jetbrains.kotlin.android.intention.AbstractAndroidResourceIntentionTest
|
||||
import org.jetbrains.kotlin.android.lint.AbstractKotlinLintTest
|
||||
import org.jetbrains.kotlin.android.quickfix.AbstractAndroidLintQuickfixTest
|
||||
@@ -1232,6 +1233,10 @@ fun main(args: Array<String>) {
|
||||
model("configuration/android-gradle", pattern = """(\w+)_before\.gradle$""", testMethod = "doTestAndroidGradle")
|
||||
}
|
||||
|
||||
testClass<AbstractAndroidIntentionTest> {
|
||||
model("android/intention", pattern = "^([\\w\\-_]+)\\.kt$")
|
||||
}
|
||||
|
||||
testClass<AbstractAndroidResourceIntentionTest> {
|
||||
model("android/resourceIntention", extension = "test", singleClass = true)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android
|
||||
|
||||
import org.jetbrains.kotlin.idea.editor.fixers.range
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
|
||||
internal fun KtClass.insideBody(offset: Int): Boolean = getBody()?.range?.contains(offset) ?: false
|
||||
@@ -0,0 +1,470 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android
|
||||
|
||||
import com.android.SdkConstants.CLASS_PARCEL
|
||||
import com.android.SdkConstants.CLASS_PARCELABLE
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.performDelayedRefactoringRequests
|
||||
import org.jetbrains.kotlin.idea.intentions.getLeftMostReceiverExpression
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.propertyDescriptor
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
|
||||
private val CREATOR_NAME = "CREATOR"
|
||||
private val PARCEL_NAME = "parcel"
|
||||
private val CREATOR_TEXT =
|
||||
"companion object $CREATOR_NAME : android.os.Parcelable.Creator<%1\$s> {\n" +
|
||||
" override fun createFromParcel($PARCEL_NAME: $CLASS_PARCEL): %1\$s {\n" +
|
||||
" return %1\$s($PARCEL_NAME)\n" +
|
||||
" }\n\n" +
|
||||
" override fun newArray(size: Int): Array<%1\$s?> {\n" +
|
||||
" return arrayOfNulls(size)\n" +
|
||||
" }\n" +
|
||||
"}"
|
||||
private val WRITE_TO_PARCEL_TEXT = "override fun writeToParcel($PARCEL_NAME: $CLASS_PARCEL, flags: Int) {\n}"
|
||||
private val WRITE_TO_PARCEL_SUPER_CALL_TEXT = "super.writeToParcel($PARCEL_NAME, flags)"
|
||||
private val WRITE_TO_PARCEL_WITH_SUPER_TEXT =
|
||||
"override fun writeToParcel($PARCEL_NAME: $CLASS_PARCEL, flags: Int) {\n$WRITE_TO_PARCEL_SUPER_CALL_TEXT\n}"
|
||||
private val DESCRIBE_CONTENTS_TEXT = "override fun describeContents(): Int {\nreturn 0\n}"
|
||||
private val CONSTRUCTOR_TEXT = "constructor($PARCEL_NAME: $CLASS_PARCEL)"
|
||||
|
||||
|
||||
fun KtClass.canAddParcelable(): Boolean =
|
||||
findParcelableSupertype() == null
|
||||
|| findCreator() == null
|
||||
|| findConstructorFromParcel() == null
|
||||
|| findWriteToParcel() == null
|
||||
|| findDescribeContents() == null
|
||||
|
||||
fun KtClass.canRedoParcelable(): Boolean = canRemoveParcelable()
|
||||
|
||||
fun KtClass.canRemoveParcelable(): Boolean =
|
||||
findParcelableSupertype()?.takeIf { it.typeReference?.isParcelableReference() ?: false }
|
||||
?: findCreator()
|
||||
?: findConstructorFromParcel()
|
||||
?: findWriteToParcel()
|
||||
?: findDescribeContents() != null
|
||||
|
||||
fun KtClass.implementParcelable() {
|
||||
val factory = KtPsiFactory(this)
|
||||
val superExtendsParcelable = superExtendsParcelable()
|
||||
|
||||
findOrCreateParcelableSupertype(factory)
|
||||
val constructor = findOrCreateConstructor(factory)
|
||||
|
||||
addFieldReads(constructor, factory)
|
||||
|
||||
val writeToParcel = findOrCreateWriteToParcel(factory, superExtendsParcelable)
|
||||
addFieldWrites(writeToParcel, factory, superExtendsParcelable)
|
||||
|
||||
findOrCreateDescribeContents(factory)
|
||||
findOrCreateCreator(factory)
|
||||
|
||||
performDelayedRefactoringRequests(project)
|
||||
save()
|
||||
}
|
||||
|
||||
fun KtClass.removeParcelableImplementation() {
|
||||
findParcelableSupertype()?.takeIf { it.typeReference?.isParcelableReference() ?: false }?.let {
|
||||
removeSuperTypeListEntry(it)
|
||||
}
|
||||
|
||||
findConstructorFromParcel()?.let {
|
||||
if (it is KtPrimaryConstructor) {
|
||||
tryDeleteInitBlock()
|
||||
}
|
||||
it.delete()
|
||||
}
|
||||
|
||||
findWriteToParcel()?.delete()
|
||||
findDescribeContents()?.delete()
|
||||
findCreator()?.delete()
|
||||
save()
|
||||
}
|
||||
|
||||
fun KtClass.reimplementParcelable() {
|
||||
removeParcelableImplementation()
|
||||
implementParcelable()
|
||||
}
|
||||
|
||||
private fun KtClass.findCreator(): KtObjectDeclaration? = companionObjects.find { it.name == CREATOR_NAME }
|
||||
|
||||
private fun KtClass.findParcelableSupertype(): KtSuperTypeListEntry? = getSuperTypeList()?.findParcelable()
|
||||
|
||||
private fun KtSuperTypeList.findParcelable() = entries?.find { it.typeReference?.isParcelableSuccessorReference() ?: false }
|
||||
|
||||
private fun KtTypeReference.isParcelableSuccessorReference() =
|
||||
analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, this]?.isSubclassOfParcelable() ?: false
|
||||
|
||||
private fun KtClass.superExtendsParcelable() = superTypeListEntries.find { it.typeReference?.extendsParcelable() ?: false } != null
|
||||
|
||||
private fun KtClass.tryDeleteInitBlock() {
|
||||
getAnonymousInitializers().forEach { initializer ->
|
||||
val block = initializer.body as? KtBlockExpression
|
||||
if (block != null) {
|
||||
block.statements.forEach { statement ->
|
||||
if (statement.isReadFromParcelPropertyAssignment()) {
|
||||
statement.delete()
|
||||
}
|
||||
}
|
||||
|
||||
if (block.statements.isEmpty()) {
|
||||
initializer.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtExpression.isReadFromParcelPropertyAssignment(): Boolean {
|
||||
if (this !is KtBinaryExpression || this.operationToken != KtTokens.EQ) {
|
||||
return false
|
||||
}
|
||||
|
||||
return this.right?.isReadFromParcel() ?: false
|
||||
}
|
||||
|
||||
private fun KtExpression.isReadFromParcel(): Boolean {
|
||||
val reference = firstChild as? KtReferenceExpression
|
||||
?: (firstChild as? KtDotQualifiedExpression)?.getLeftMostReceiverExpression() as? KtReferenceExpression ?: return false
|
||||
val target = reference.analyze(BodyResolveMode.PARTIAL)[BindingContext.REFERENCE_TARGET, reference] ?: return false
|
||||
return (target as? ParameterDescriptor)?.type?.fqNameEquals(CLASS_PARCEL) ?: false
|
||||
}
|
||||
|
||||
private fun KtClass.addFieldWrites(function: KtFunction, factory: KtPsiFactory, callSuper: Boolean) {
|
||||
val bodyExpression = function.bodyExpression
|
||||
if (bodyExpression !is KtBlockExpression || !bodyExpression.isEmptyWriteToParcel(callSuper)) {
|
||||
return
|
||||
}
|
||||
|
||||
val propertyParameterDescriptors = primaryConstructor?.valueParameters?.mapNotNull { it.propertyDescriptor } ?: emptyList()
|
||||
|
||||
val propertyDescriptors = declarations
|
||||
.filter { it.isParcelableProperty() }
|
||||
.mapNotNull { it.descriptor as? PropertyDescriptor }
|
||||
|
||||
val parcelName = function.valueParameters[0].name ?: return
|
||||
val flagsName = function.valueParameters[1].name ?: return
|
||||
val blockText =
|
||||
(propertyParameterDescriptors + propertyDescriptors)
|
||||
.mapNotNull { it.formatWriteToParcel(parcelName, flagsName) }
|
||||
.joinToString(separator = "\n")
|
||||
|
||||
val block = factory.createBlock(
|
||||
if (callSuper)
|
||||
WRITE_TO_PARCEL_SUPER_CALL_TEXT + if (blockText.isNotBlank()) "\n$blockText" else ""
|
||||
else blockText
|
||||
)
|
||||
|
||||
bodyExpression.replace(block)
|
||||
}
|
||||
|
||||
private fun KtClass.addFieldReads(constructor: KtConstructor<*>, factory: KtPsiFactory) {
|
||||
val bodyExpression = constructor.getBodyExpression()
|
||||
if (bodyExpression != null && bodyExpression.statements.isNotEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val parcelName = constructor.getValueParameters().firstOrNull()?.name ?: return
|
||||
val parcelableProperties = declarations
|
||||
.filter { it.isParcelableProperty() }
|
||||
.mapNotNull { it.descriptor as? PropertyDescriptor }
|
||||
|
||||
if (parcelableProperties.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val blockText = parcelableProperties
|
||||
.mapNotNull { descriptor -> descriptor.formatReadFromParcel(parcelName)?.let { "${descriptor.name} = $it" } }
|
||||
.joinToString(separator = "\n")
|
||||
|
||||
val block = factory.createBlock(blockText)
|
||||
|
||||
if (constructor is KtPrimaryConstructor) {
|
||||
val initializer = factory.createAnonymousInitializer()
|
||||
initializer.body?.replace(block)
|
||||
addDeclaration(initializer).apply {
|
||||
addNewLineBeforeDeclaration()
|
||||
addToShorteningWaitSet()
|
||||
}
|
||||
}
|
||||
else {
|
||||
bodyExpression?.replace(block) ?: constructor.add(block)
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtDeclaration.isParcelableProperty(): Boolean =
|
||||
this is KtProperty && isVar && !hasDelegate() && !isTransient() && getter == null && setter == null
|
||||
|
||||
private fun KtProperty.isTransient() = annotationEntries.find { it.isTransientAnnotation() } != null
|
||||
|
||||
private fun KtAnnotationEntry.isTransientAnnotation(): Boolean =
|
||||
typeReference?.analyze(BodyResolveMode.PARTIAL)?.get(BindingContext.TYPE, typeReference)?.fqNameEquals("kotlin.jvm.Transient") ?: false
|
||||
|
||||
private fun KtExpression.isCallToSuperWriteToParcel() =
|
||||
this is KtDotQualifiedExpression
|
||||
&& receiverExpression is KtSuperExpression
|
||||
&& (selectorExpression as? KtCallExpression)?.calleeExpression?.text == "writeToParcel"
|
||||
|
||||
private fun KtBlockExpression.isEmptyWriteToParcel(callSuper: Boolean): Boolean =
|
||||
if (callSuper) {
|
||||
statements.isEmpty() || statements.size == 1 && statements.first().isCallToSuperWriteToParcel()
|
||||
}
|
||||
else {
|
||||
statements.isEmpty()
|
||||
}
|
||||
|
||||
private fun PropertyDescriptor.formatReadFromParcel(parcelName: String): String? {
|
||||
val type = returnType ?: return null
|
||||
|
||||
fun KotlinType.formatJavaClassloader() = "${this.constructor.declarationDescriptor?.fqNameSafe}::class.java.classLoader"
|
||||
|
||||
// There is no read/write short array methods
|
||||
if (KotlinBuiltIns.isPrimitiveArray(type) && KotlinBuiltIns.getPrimitiveArrayElementType(type) != PrimitiveType.SHORT) {
|
||||
return "$parcelName.create${type.getName()}()"
|
||||
}
|
||||
|
||||
|
||||
if (type.isMarkedNullable && KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType(type)) {
|
||||
return "$parcelName.readValue(${type.formatJavaClassloader()}) as? ${type.getName()}"
|
||||
}
|
||||
|
||||
if (KotlinBuiltIns.isPrimitiveType(type)) {
|
||||
return when {
|
||||
KotlinBuiltIns.isBoolean(type) -> "$parcelName.readByte() != 0.toByte()"
|
||||
KotlinBuiltIns.isShort(type) -> "$parcelName.readInt().toShort()"
|
||||
KotlinBuiltIns.isChar(type) -> "$parcelName.readInt().toChar()"
|
||||
else -> "$parcelName.read${type.getName()}()"
|
||||
}
|
||||
}
|
||||
|
||||
return when {
|
||||
KotlinBuiltIns.isCharSequenceOrNullableCharSequence(type) -> "$parcelName.readString()"
|
||||
KotlinBuiltIns.isStringOrNullableString(type) -> "$parcelName.readString()"
|
||||
type.isArrayOfParcelable() -> "$parcelName.createTypedArray(${type.arguments.single().type.getName()}.CREATOR)"
|
||||
type.isListOfParcelable() -> "$parcelName.createTypedArrayList(${type.arguments.single().type.getName()}.CREATOR)"
|
||||
type.isArrayOfIBinder() -> "$parcelName.createBinderArray()"
|
||||
type.isListOfIBinder() -> "$parcelName.createBinderArrayList()"
|
||||
type.isArrayOfString() -> "$parcelName.createStringArray()"
|
||||
type.isListOfString() -> "$parcelName.createStringArrayList()"
|
||||
type.isSparseBooleanArray() -> "$parcelName.readSparseBooleanArray()"
|
||||
type.isBundle() -> "$parcelName.readBundle(${type.formatJavaClassloader()})"
|
||||
type.isIBinder() -> "$parcelName.readStrongBinder()"
|
||||
type.isSubclassOfParcelable(true) -> "$parcelName.readParcelable(${type.formatJavaClassloader()})" // This one should go last
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun PropertyDescriptor.formatWriteToParcel(parcelName: String, flagsName: String): String? {
|
||||
val type = returnType ?: return null
|
||||
|
||||
// There is no read/write short array methods
|
||||
if (KotlinBuiltIns.isPrimitiveArray(type) && KotlinBuiltIns.getPrimitiveArrayElementType(type) != PrimitiveType.SHORT) {
|
||||
return "$parcelName.write${type.getName()}($name)"
|
||||
}
|
||||
|
||||
if (type.isMarkedNullable) {
|
||||
if (KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType(type)) {
|
||||
return "$parcelName.writeValue($name)"
|
||||
}
|
||||
else if (KotlinBuiltIns.isCharSequenceOrNullableCharSequence(type)) {
|
||||
return "$parcelName.writeString($name?.toString())"
|
||||
}
|
||||
}
|
||||
|
||||
if (KotlinBuiltIns.isPrimitiveType(type)) {
|
||||
return when {
|
||||
KotlinBuiltIns.isBoolean(type) -> "$parcelName.writeByte(if ($name) 1 else 0)"
|
||||
KotlinBuiltIns.isShort(type) -> "$parcelName.writeInt($name.toInt())"
|
||||
KotlinBuiltIns.isChar(type) -> "$parcelName.writeInt($name.toInt())"
|
||||
else -> "$parcelName.write${type.getName()}($name)"
|
||||
}
|
||||
}
|
||||
|
||||
return when {
|
||||
KotlinBuiltIns.isCharSequence(type) -> "$parcelName.writeString($name.toString())"
|
||||
KotlinBuiltIns.isStringOrNullableString(type) -> "$parcelName.writeString($name)"
|
||||
type.isArrayOfParcelable() -> "$parcelName.writeTypedArray($name, $flagsName)"
|
||||
type.isListOfParcelable() -> "$parcelName.writeTypedList($name)"
|
||||
type.isArrayOfIBinder() -> "$parcelName.writeBinderArray($name)"
|
||||
type.isListOfIBinder() -> "$parcelName.writeBinderList($name)"
|
||||
type.isArrayOfString() -> "$parcelName.writeStringArray($name)"
|
||||
type.isListOfString() -> "$parcelName.writeStringList($name)"
|
||||
type.isSparseBooleanArray() -> "$parcelName.writeSparseBooleanArray($name)"
|
||||
type.isBundle() -> "$parcelName.writeBundle($name)"
|
||||
type.isIBinder() -> "$parcelName.writeStrongBinder($name)"
|
||||
type.isSubclassOfParcelable(true) -> "$parcelName.writeParcelable($name, $flagsName)" // This one should go last
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtClass.findOrCreateCreator(factory: KtPsiFactory): KtClassOrObject {
|
||||
findCreator()?.let {
|
||||
return it
|
||||
}
|
||||
|
||||
val creator = factory.createObject(CREATOR_TEXT.format(name))
|
||||
return addDeclaration(creator).apply { addToShorteningWaitSet() }
|
||||
}
|
||||
|
||||
private fun KtClass.findOrCreateParcelableSupertype(factory: KtPsiFactory): KtSuperTypeListEntry? {
|
||||
findParcelableSupertype()?.let {
|
||||
return it
|
||||
}
|
||||
|
||||
val supertypeEntry = factory.createSuperTypeEntry(CLASS_PARCELABLE)
|
||||
return addSuperTypeListEntry(supertypeEntry).apply { addToShorteningWaitSet() }
|
||||
}
|
||||
|
||||
private fun KtClass.save() = FileDocumentManager.getInstance().getDocument(containingFile.virtualFile)?.let {
|
||||
PsiDocumentManager.getInstance(project).commitDocument(it)
|
||||
}
|
||||
|
||||
private fun KtClass.findOrCreateConstructor(factory: KtPsiFactory): KtConstructor<*> {
|
||||
findConstructorFromParcel()?.let {
|
||||
return it
|
||||
}
|
||||
|
||||
createPrimaryConstructorIfAbsent()
|
||||
return createSecondaryConstructor(factory).apply {
|
||||
addToShorteningWaitSet()
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtClass.createSecondaryConstructor(factory: KtPsiFactory): KtConstructor<*> {
|
||||
val constructorText = primaryConstructor?.let { constructor ->
|
||||
val arguments = constructor.valueParameters.map {
|
||||
it?.propertyDescriptor?.formatReadFromParcel(PARCEL_NAME) ?: "TODO(\"${it?.name}\")"
|
||||
}
|
||||
|
||||
val argumentList = arguments.joinToString(
|
||||
prefix = if (arguments.size > 1) "(\n" else "(",
|
||||
postfix = ")",
|
||||
separator = if (arguments.size > 1) ",\n" else ", ")
|
||||
|
||||
"$CONSTRUCTOR_TEXT :this$argumentList {\n}"
|
||||
} ?: "$CONSTRUCTOR_TEXT {\n}"
|
||||
|
||||
val constructor = factory.createSecondaryConstructor(constructorText)
|
||||
val lastProperty = declarations.findLast { it is KtProperty }
|
||||
if (lastProperty != null) {
|
||||
return addDeclarationAfter(constructor, lastProperty).apply { addNewLineBeforeDeclaration() }
|
||||
}
|
||||
else {
|
||||
val firstFunction = declarations.find { it is KtFunction }
|
||||
return addDeclarationBefore(constructor, firstFunction).apply { addNewLineBeforeDeclaration() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtTypeReference.extendsParcelable(): Boolean =
|
||||
analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, this]?.isSubclassOfParcelable(true) ?: false
|
||||
|
||||
private fun KtClass.findWriteToParcel() = declarations.find { it.isWriteToParcel() }
|
||||
|
||||
private fun KtDeclaration.isWriteToParcel(): Boolean = this is KtFunction && name == "writeToParcel" && valueParameters.let {
|
||||
it.size == 2 && it[0].isParcelParameter() && (it[1].typeReference?.fqNameEquals("kotlin.Int") ?: false)
|
||||
}
|
||||
|
||||
private fun KtClass.findOrCreateWriteToParcel(factory: KtPsiFactory, callSuper: Boolean): KtFunction {
|
||||
findWriteToParcel()?.let {
|
||||
return it as KtFunction
|
||||
}
|
||||
|
||||
val writeToParcel = factory.createFunction(if (callSuper) WRITE_TO_PARCEL_WITH_SUPER_TEXT else WRITE_TO_PARCEL_TEXT)
|
||||
return addDeclaration(writeToParcel).apply {
|
||||
addNewLineBeforeDeclaration()
|
||||
addToShorteningWaitSet()
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtClass.findDescribeContents() = declarations.find { it.isDescribeContents() }
|
||||
|
||||
private fun KtDeclaration.isDescribeContents(): Boolean = this is KtFunction &&
|
||||
name == "describeContents" &&
|
||||
valueParameters.isEmpty()
|
||||
|
||||
private fun KtClass.findOrCreateDescribeContents(factory: KtPsiFactory): KtFunction {
|
||||
findDescribeContents()?.let {
|
||||
return it as KtFunction
|
||||
}
|
||||
|
||||
val describeContents = factory.createFunction(DESCRIBE_CONTENTS_TEXT)
|
||||
return addDeclaration(describeContents).apply {
|
||||
addNewLineBeforeDeclaration()
|
||||
addToShorteningWaitSet()
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtClass.findConstructorFromParcel(): KtConstructor<*>? =
|
||||
primaryConstructor?.takeIf { it.isConstructorFromParcel() } ?: secondaryConstructors.find { it.isConstructorFromParcel() }
|
||||
|
||||
private fun KtConstructor<*>.isConstructorFromParcel(): Boolean = getValueParameters().let {
|
||||
it.size == 1 && it.single().isParcelParameter()
|
||||
}
|
||||
|
||||
private fun KtParameter.isParcelParameter(): Boolean = typeReference?.fqNameEquals(CLASS_PARCEL) ?: false
|
||||
|
||||
private fun KtTypeReference.isParcelableReference() = fqNameEquals(CLASS_PARCELABLE)
|
||||
|
||||
private fun KtTypeReference.fqNameEquals(fqName: String) =
|
||||
analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, this]?.fqNameEquals(fqName) ?: false
|
||||
|
||||
private fun KotlinType.getName() = constructor.declarationDescriptor?.name
|
||||
|
||||
private fun KotlinType.fqNameEquals(fqName: String) = constructor.declarationDescriptor?.fqNameSafe?.asString() == fqName
|
||||
|
||||
private fun KotlinType.isSubclassOfParcelable(strict: Boolean = false): Boolean = isSubclassOf(FqName(CLASS_PARCELABLE), strict)
|
||||
|
||||
private fun KotlinType.isIBinder(): Boolean = fqNameEquals("android.os.IBinder")
|
||||
|
||||
private fun KotlinType.isArrayOfParcelable(): Boolean =
|
||||
KotlinBuiltIns.isArray(this) && arguments.singleOrNull()?.type?.isSubclassOfParcelable(true) ?: false
|
||||
|
||||
private fun KotlinType.isArrayOfIBinder(): Boolean =
|
||||
KotlinBuiltIns.isArray(this) && arguments.singleOrNull()?.type?.isIBinder() ?: false
|
||||
|
||||
private fun KotlinType.isArrayOfString(): Boolean =
|
||||
KotlinBuiltIns.isArray(this) && KotlinBuiltIns.isStringOrNullableString(arguments.singleOrNull()?.type)
|
||||
|
||||
private fun KotlinType.isListOfString(): Boolean =
|
||||
KotlinBuiltIns.isListOrNullableList(this) && KotlinBuiltIns.isStringOrNullableString(arguments.singleOrNull()?.type)
|
||||
|
||||
private fun KotlinType.isListOfParcelable(): Boolean =
|
||||
KotlinBuiltIns.isListOrNullableList(this) && arguments.singleOrNull()?.type?.isSubclassOfParcelable(true) ?: false
|
||||
|
||||
private fun KotlinType.isListOfIBinder(): Boolean =
|
||||
KotlinBuiltIns.isListOrNullableList(this) && arguments.singleOrNull()?.type?.isIBinder() ?: false
|
||||
|
||||
private fun KotlinType.isSparseBooleanArray(): Boolean = fqNameEquals("android.util.SparseBooleanArray")
|
||||
|
||||
private fun KotlinType.isBundle(): Boolean = fqNameEquals("android.os.Bundle")
|
||||
|
||||
private fun <T: KtDeclaration> T.addNewLineBeforeDeclaration() = parent.addBefore(KtPsiFactory(this).createNewLine(), this)
|
||||
@@ -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.android
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
internal fun KotlinType.fqNameSafe() = constructor.declarationDescriptor?.fqNameSafe
|
||||
|
||||
internal fun KotlinType.isSubclassOf(className: FqName, strict: Boolean = false): Boolean =
|
||||
(!strict && fqNameSafe() == className) || constructor.supertypes.any {
|
||||
className == it.fqNameSafe() || it.isSubclassOf(className, true)
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.intention
|
||||
|
||||
import com.intellij.codeInsight.intention.HighPriorityAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.android.facet.AndroidFacet
|
||||
import org.jetbrains.android.util.AndroidBundle
|
||||
import org.jetbrains.kotlin.android.canAddParcelable
|
||||
import org.jetbrains.kotlin.android.implementParcelable
|
||||
import org.jetbrains.kotlin.android.insideBody
|
||||
import org.jetbrains.kotlin.idea.intentions.SelfTargetingIntention
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
|
||||
|
||||
class ImplementParcelableAction :
|
||||
SelfTargetingIntention<KtClass>(KtClass::class.java, AndroidBundle.message("implement.parcelable.intention.text")),
|
||||
HighPriorityAction {
|
||||
override fun isApplicableTo(element: KtClass, caretOffset: Int): Boolean =
|
||||
AndroidFacet.getInstance(element) != null &&
|
||||
!element.insideBody(caretOffset) &&
|
||||
element.canAddParcelable()
|
||||
|
||||
override fun applyTo(element: KtClass, editor: Editor?) {
|
||||
element.implementParcelable()
|
||||
}
|
||||
|
||||
override fun startInWriteAction(): Boolean = true
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.intention
|
||||
|
||||
import com.intellij.codeInsight.intention.HighPriorityAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.android.facet.AndroidFacet
|
||||
import org.jetbrains.android.util.AndroidBundle
|
||||
import org.jetbrains.kotlin.android.canRedoParcelable
|
||||
import org.jetbrains.kotlin.android.insideBody
|
||||
import org.jetbrains.kotlin.android.reimplementParcelable
|
||||
import org.jetbrains.kotlin.idea.intentions.SelfTargetingIntention
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
|
||||
|
||||
class RedoParcelableAction :
|
||||
SelfTargetingIntention<KtClass>(KtClass::class.java, AndroidBundle.message("redo.parcelable.intention.text")),
|
||||
HighPriorityAction {
|
||||
override fun isApplicableTo(element: KtClass, caretOffset: Int): Boolean =
|
||||
AndroidFacet.getInstance(element) != null &&
|
||||
!element.insideBody(caretOffset) &&
|
||||
element.canRedoParcelable()
|
||||
|
||||
override fun applyTo(element: KtClass, editor: Editor?) {
|
||||
element.reimplementParcelable()
|
||||
}
|
||||
|
||||
override fun startInWriteAction(): Boolean = true
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.intention
|
||||
|
||||
import com.intellij.codeInsight.intention.HighPriorityAction
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import org.jetbrains.android.facet.AndroidFacet
|
||||
import org.jetbrains.android.util.AndroidBundle
|
||||
import org.jetbrains.kotlin.android.canRemoveParcelable
|
||||
import org.jetbrains.kotlin.android.insideBody
|
||||
import org.jetbrains.kotlin.android.removeParcelableImplementation
|
||||
import org.jetbrains.kotlin.idea.intentions.SelfTargetingIntention
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
|
||||
|
||||
class RemoveParcelableAction :
|
||||
SelfTargetingIntention<KtClass>(KtClass::class.java, AndroidBundle.message("remove.parcelable.intention.text")),
|
||||
HighPriorityAction {
|
||||
override fun isApplicableTo(element: KtClass, caretOffset: Int): Boolean =
|
||||
AndroidFacet.getInstance(element) != null &&
|
||||
!element.insideBody(caretOffset) &&
|
||||
element.canRemoveParcelable()
|
||||
|
||||
override fun applyTo(element: KtClass, editor: Editor?) {
|
||||
element.removeParcelableImplementation()
|
||||
}
|
||||
|
||||
override fun startInWriteAction(): Boolean = true
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.intention
|
||||
|
||||
import com.android.SdkConstants
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.util.PathUtil
|
||||
import org.jetbrains.kotlin.android.KotlinAndroidTestCase
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
|
||||
abstract class AbstractAndroidIntentionTest : KotlinAndroidTestCase() {
|
||||
fun doTest(path: String) {
|
||||
val testFile = File(path)
|
||||
val testFileText = FileUtil.loadFile(testFile)
|
||||
val intentionClassName = InTextDirectivesUtils.findStringWithPrefixes(testFileText, "// INTENTION_CLASS: ")
|
||||
?: error("Intention class not found!")
|
||||
|
||||
val notAvailable = InTextDirectivesUtils.isDirectiveDefined(testFileText, "// NOT_AVAILABLE")
|
||||
val withRuntime = InTextDirectivesUtils.isDirectiveDefined(testFileText, "// WITH_RUNTIME")
|
||||
|
||||
try {
|
||||
if (withRuntime) {
|
||||
ConfigLibraryUtil.configureKotlinRuntime(myFixture.module)
|
||||
}
|
||||
|
||||
val sourceFile = myFixture.copyFileToProject(path, "src/${PathUtil.getFileName(path)}")
|
||||
myFixture.configureFromExistingVirtualFile(sourceFile)
|
||||
|
||||
val intention = Class.forName(intentionClassName).newInstance() as? IntentionAction ?: error("Failed to create intention!")
|
||||
if (!intention.isAvailable(myFixture.project, myFixture.editor, myFixture.file)) {
|
||||
if (notAvailable) {
|
||||
return
|
||||
}
|
||||
|
||||
error("Intention is not available!")
|
||||
}
|
||||
|
||||
myFixture.launchAction(intention)
|
||||
myFixture.checkResultByFile("$path.expected")
|
||||
}
|
||||
finally {
|
||||
if (withRuntime) {
|
||||
ConfigLibraryUtil.unConfigureKotlinRuntime(myFixture.module)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createManifest() {
|
||||
myFixture.copyFileToProject("idea/testData/android/AndroidManifest.xml", SdkConstants.FN_ANDROID_MANIFEST_XML)
|
||||
}
|
||||
|
||||
override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory()
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.intention;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
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("idea/testData/android/intention")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class AndroidIntentionTestGenerated extends AbstractAndroidIntentionTest {
|
||||
public void testAllFilesPresentInIntention() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/android/intention"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/android/intention/implementParcelable")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ImplementParcelable extends AbstractAndroidIntentionTest {
|
||||
public void testAllFilesPresentInImplementParcelable() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/android/intention/implementParcelable"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("allNullableTypes.kt")
|
||||
public void testAllNullableTypes() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/implementParcelable/allNullableTypes.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("allTypes.kt")
|
||||
public void testAllTypes() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/implementParcelable/allTypes.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("alreadyImplemented.kt")
|
||||
public void testAlreadyImplemented() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/implementParcelable/alreadyImplemented.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("constructorProperties.kt")
|
||||
public void testConstructorProperties() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/implementParcelable/constructorProperties.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("constructorPropertiesWithParameters.kt")
|
||||
public void testConstructorPropertiesWithParameters() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/implementParcelable/constructorPropertiesWithParameters.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("missingConstructor.kt")
|
||||
public void testMissingConstructor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/implementParcelable/missingConstructor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("missingDescribeContents.kt")
|
||||
public void testMissingDescribeContents() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/implementParcelable/missingDescribeContents.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("missingWriteToParcel.kt")
|
||||
public void testMissingWriteToParcel() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/implementParcelable/missingWriteToParcel.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/implementParcelable/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withTransient.kt")
|
||||
public void testWithTransient() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/implementParcelable/withTransient.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/android/intention/redoParcelable")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class RedoParcelable extends AbstractAndroidIntentionTest {
|
||||
public void testAllFilesPresentInRedoParcelable() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/android/intention/redoParcelable"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("indirectParcelable.kt")
|
||||
public void testIndirectParcelable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/redoParcelable/indirectParcelable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("init.kt")
|
||||
public void testInit() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/redoParcelable/init.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("initWithExtraStatements.kt")
|
||||
public void testInitWithExtraStatements() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/redoParcelable/initWithExtraStatements.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noParcelable.kt")
|
||||
public void testNoParcelable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/redoParcelable/noParcelable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("oldField.kt")
|
||||
public void testOldField() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/redoParcelable/oldField.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("oldFieldSecondary.kt")
|
||||
public void testOldFieldSecondary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/redoParcelable/oldFieldSecondary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/redoParcelable/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/android/intention/removeParcelable")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class RemoveParcelable extends AbstractAndroidIntentionTest {
|
||||
public void testAllFilesPresentInRemoveParcelable() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/android/intention/removeParcelable"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("inderectParcelable.kt")
|
||||
public void testInderectParcelable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/removeParcelable/inderectParcelable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("init.kt")
|
||||
public void testInit() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/removeParcelable/init.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("initWithExtraStatements.kt")
|
||||
public void testInitWithExtraStatements() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/removeParcelable/initWithExtraStatements.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noParcelable.kt")
|
||||
public void testNoParcelable() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/removeParcelable/noParcelable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/intention/removeParcelable/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -58,7 +58,7 @@ abstract class AbstractAndroidLintQuickfixTest : KotlinAndroidTestCase() {
|
||||
myFixture.checkResultByFile(path + ".expected")
|
||||
}
|
||||
else {
|
||||
assertNull("Intention should not be availabale", myFixture.availableIntentions.find { it.text == intentionText })
|
||||
assertNull("Intention should not be available", myFixture.availableIntentions.find { it.text == intentionText })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+21
@@ -36,6 +36,27 @@ public class AndroidLintQuickfixTestGenerated extends AbstractAndroidLintQuickfi
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/android/lintQuickfix"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/android/lintQuickfix/parcelable")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Parcelable extends AbstractAndroidLintQuickfixTest {
|
||||
public void testAllFilesPresentInParcelable() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/android/lintQuickfix/parcelable"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("missingCreator.kt")
|
||||
public void testMissingCreator() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/lintQuickfix/parcelable/missingCreator.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noImplementation.kt")
|
||||
public void testNoImplementation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/lintQuickfix/parcelable/noImplementation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/android/lintQuickfix/requiresApi")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
class SomeData(val number: Int, val text: String, val flag: Boolean) : Parcelable {
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readInt(),
|
||||
parcel.readString(),
|
||||
parcel.readByte() != 0.toByte()) {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(number)
|
||||
parcel.writeString(text)
|
||||
parcel.writeByte(if (flag) 1 else 0)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<SomeData> {
|
||||
override fun createFromParcel(parcel: Parcel): SomeData {
|
||||
return SomeData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<SomeData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
class SomeData(val number: Int, val text: String, val flag: Boolean)
|
||||
@@ -0,0 +1,4 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention implements the methods and the CREATOR object needed for Parcelable.</body>
|
||||
</html>
|
||||
@@ -0,0 +1,27 @@
|
||||
class SomeData(val number: Int, val text: String, val flag: Boolean) : Parcelable {
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readInt(),
|
||||
parcel.readString(),
|
||||
parcel.readByte() != 0.toByte()) {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(number)
|
||||
parcel.writeString(text)
|
||||
parcel.writeByte(if (flag) 1 else 0)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<SomeData> {
|
||||
override fun createFromParcel(parcel: Parcel): SomeData {
|
||||
return SomeData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<SomeData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
class SomeData(val number: Int, val text: String, val flag: Boolean) : Parcelable {
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readString()) {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(oldField)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 42
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<SomeData> {
|
||||
override fun createFromParcel(parcel: Parcel): SomeData {
|
||||
return SomeData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<SomeData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention regenerates the methods and the CREATOR object which implements Parcelable. <b>Warning:</b> Your custom code will be removed.
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,3 @@
|
||||
class SomeData(val number: Int, val text: String, val flag: Boolean) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
class SomeData(val number: Int, val text: String, val flag: Boolean) : Parcelable {
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readInt(),
|
||||
parcel.readString(),
|
||||
parcel.readByte() != 0.toByte()) {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(number)
|
||||
parcel.writeString(text)
|
||||
parcel.writeByte(if (flag) 1 else 0)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<SomeData> {
|
||||
override fun createFromParcel(parcel: Parcel): SomeData {
|
||||
return SomeData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<SomeData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention removes the methods and the CREATOR object which implements Parcelable. <b>Warning:</b> Your custom code will be removed.
|
||||
</body>
|
||||
</html>
|
||||
@@ -23,6 +23,20 @@
|
||||
<category>Kotlin Android</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.android.intention.ImplementParcelableAction</className>
|
||||
<category>Kotlin Android</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.android.intention.RemoveParcelableAction</className>
|
||||
<category>Kotlin Android</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.android.intention.RedoParcelableAction</className>
|
||||
<category>Kotlin Android</category>
|
||||
</intentionAction>
|
||||
|
||||
<codeInsight.unresolvedReferenceQuickFixProvider
|
||||
implementation="org.jetbrains.kotlin.android.inspection.KotlinAndroidResourceQuickFixProvider"/>
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.util.SparseBooleanArray
|
||||
import android.util.SparseIntArray
|
||||
|
||||
open class BaseParcelable(parcel: Parcel) : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<BaseParcelable> {
|
||||
override fun createFromParcel(parcel: Parcel): BaseParcelable {
|
||||
return BaseParcelable(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<BaseParcelable?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class <caret>MyData {
|
||||
|
||||
val delegated by lazy { 0 }
|
||||
val readonlyField = true
|
||||
|
||||
var listOfStrings: List<String?>? = null
|
||||
var listOfIBinder: List<IBinder?>? = null
|
||||
|
||||
var arrayfield1: IntArray? = null
|
||||
var arrayfield2: Array<String>? = null
|
||||
var arrayfield3: LongArray? = null
|
||||
var arrayfield4: ByteArray? = null
|
||||
var arrayfield5: CharArray? = null
|
||||
var arrayfield6: ShortArray? = null // No method for Short
|
||||
var arrayfield7: FloatArray? = null
|
||||
var arrayfield8: DoubleArray? = null
|
||||
var arrayfield9: BooleanArray? = null
|
||||
var arrayfield10: Array<CharSequence>? = null // No method for CharSequence
|
||||
var arrayfield11: Array<IBinder>? = null
|
||||
|
||||
var field1: Int? = 0
|
||||
var field2: String? = ""
|
||||
var field3: Long? = 0
|
||||
var field4: Byte? = 0
|
||||
var field5: Char? = '\u0000'
|
||||
var field6: Short? = 0
|
||||
var field7: Float? = 0.0f
|
||||
var field8: Double? = 0.0
|
||||
var field9: Boolean? = false
|
||||
var field10: CharSequence? = ""
|
||||
var field11: SparseBooleanArray? = null
|
||||
var field12: SparseIntArray? = null // read/write methods will be available starting from android O
|
||||
var field13: Bundle? = null
|
||||
var field14: IBinder? = null
|
||||
|
||||
var goodArray: Array<BaseParcelable?>? = emptyArray()
|
||||
var badArray: Array<Parcelable?>? = emptyArray()
|
||||
|
||||
var goodList: List<BaseParcelable?>? = emptyList()
|
||||
var badList: List<Parcelable?>? = emptyList()
|
||||
|
||||
var parcelableProperty: BaseParcelable?
|
||||
val uninitializedVal: Int?
|
||||
|
||||
val fieldWIthGetter: Int?
|
||||
get() {
|
||||
return 0
|
||||
}
|
||||
|
||||
var fieldWithCustomGetterAndSetter: Int? = 0
|
||||
get() {
|
||||
return field
|
||||
}
|
||||
set(value: Int?) {
|
||||
field = value
|
||||
}
|
||||
}
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.util.SparseBooleanArray
|
||||
import android.util.SparseIntArray
|
||||
|
||||
open class BaseParcelable(parcel: Parcel) : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<BaseParcelable> {
|
||||
override fun createFromParcel(parcel: Parcel): BaseParcelable {
|
||||
return BaseParcelable(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<BaseParcelable?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MyData() : Parcelable {
|
||||
|
||||
val delegated by lazy { 0 }
|
||||
val readonlyField = true
|
||||
|
||||
var listOfStrings: List<String?>? = null
|
||||
var listOfIBinder: List<IBinder?>? = null
|
||||
|
||||
var arrayfield1: IntArray? = null
|
||||
var arrayfield2: Array<String>? = null
|
||||
var arrayfield3: LongArray? = null
|
||||
var arrayfield4: ByteArray? = null
|
||||
var arrayfield5: CharArray? = null
|
||||
var arrayfield6: ShortArray? = null // No method for Short
|
||||
var arrayfield7: FloatArray? = null
|
||||
var arrayfield8: DoubleArray? = null
|
||||
var arrayfield9: BooleanArray? = null
|
||||
var arrayfield10: Array<CharSequence>? = null // No method for CharSequence
|
||||
var arrayfield11: Array<IBinder>? = null
|
||||
|
||||
var field1: Int? = 0
|
||||
var field2: String? = ""
|
||||
var field3: Long? = 0
|
||||
var field4: Byte? = 0
|
||||
var field5: Char? = '\u0000'
|
||||
var field6: Short? = 0
|
||||
var field7: Float? = 0.0f
|
||||
var field8: Double? = 0.0
|
||||
var field9: Boolean? = false
|
||||
var field10: CharSequence? = ""
|
||||
var field11: SparseBooleanArray? = null
|
||||
var field12: SparseIntArray? = null // read/write methods will be available starting from android O
|
||||
var field13: Bundle? = null
|
||||
var field14: IBinder? = null
|
||||
|
||||
var goodArray: Array<BaseParcelable?>? = emptyArray()
|
||||
var badArray: Array<Parcelable?>? = emptyArray()
|
||||
|
||||
var goodList: List<BaseParcelable?>? = emptyList()
|
||||
var badList: List<Parcelable?>? = emptyList()
|
||||
|
||||
var parcelableProperty: BaseParcelable?
|
||||
val uninitializedVal: Int?
|
||||
|
||||
val fieldWIthGetter: Int?
|
||||
get() {
|
||||
return 0
|
||||
}
|
||||
|
||||
var fieldWithCustomGetterAndSetter: Int? = 0
|
||||
get() {
|
||||
return field
|
||||
}
|
||||
set(value: Int?) {
|
||||
field = value
|
||||
}
|
||||
|
||||
constructor(parcel: Parcel) : this() {
|
||||
listOfStrings = parcel.createStringArrayList()
|
||||
listOfIBinder = parcel.createBinderArrayList()
|
||||
arrayfield1 = parcel.createIntArray()
|
||||
arrayfield2 = parcel.createStringArray()
|
||||
arrayfield3 = parcel.createLongArray()
|
||||
arrayfield4 = parcel.createByteArray()
|
||||
arrayfield5 = parcel.createCharArray()
|
||||
arrayfield7 = parcel.createFloatArray()
|
||||
arrayfield8 = parcel.createDoubleArray()
|
||||
arrayfield9 = parcel.createBooleanArray()
|
||||
arrayfield11 = parcel.createBinderArray()
|
||||
field1 = parcel.readValue(Int::class.java.classLoader) as? Int
|
||||
field2 = parcel.readString()
|
||||
field3 = parcel.readValue(Long::class.java.classLoader) as? Long
|
||||
field4 = parcel.readValue(Byte::class.java.classLoader) as? Byte
|
||||
field5 = parcel.readValue(Char::class.java.classLoader) as? Char
|
||||
field6 = parcel.readValue(Short::class.java.classLoader) as? Short
|
||||
field7 = parcel.readValue(Float::class.java.classLoader) as? Float
|
||||
field8 = parcel.readValue(Double::class.java.classLoader) as? Double
|
||||
field9 = parcel.readValue(Boolean::class.java.classLoader) as? Boolean
|
||||
field10 = parcel.readString()
|
||||
field11 = parcel.readSparseBooleanArray()
|
||||
field13 = parcel.readBundle(Bundle::class.java.classLoader)
|
||||
field14 = parcel.readStrongBinder()
|
||||
goodArray = parcel.createTypedArray(BaseParcelable)
|
||||
goodList = parcel.createTypedArrayList(BaseParcelable)
|
||||
parcelableProperty = parcel.readParcelable(BaseParcelable::class.java.classLoader)
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeStringList(listOfStrings)
|
||||
parcel.writeBinderList(listOfIBinder)
|
||||
parcel.writeIntArray(arrayfield1)
|
||||
parcel.writeStringArray(arrayfield2)
|
||||
parcel.writeLongArray(arrayfield3)
|
||||
parcel.writeByteArray(arrayfield4)
|
||||
parcel.writeCharArray(arrayfield5)
|
||||
parcel.writeFloatArray(arrayfield7)
|
||||
parcel.writeDoubleArray(arrayfield8)
|
||||
parcel.writeBooleanArray(arrayfield9)
|
||||
parcel.writeBinderArray(arrayfield11)
|
||||
parcel.writeValue(field1)
|
||||
parcel.writeString(field2)
|
||||
parcel.writeValue(field3)
|
||||
parcel.writeValue(field4)
|
||||
parcel.writeValue(field5)
|
||||
parcel.writeValue(field6)
|
||||
parcel.writeValue(field7)
|
||||
parcel.writeValue(field8)
|
||||
parcel.writeValue(field9)
|
||||
parcel.writeString(field10?.toString())
|
||||
parcel.writeSparseBooleanArray(field11)
|
||||
parcel.writeBundle(field13)
|
||||
parcel.writeStrongBinder(field14)
|
||||
parcel.writeTypedArray(goodArray, flags)
|
||||
parcel.writeTypedList(goodList)
|
||||
parcel.writeParcelable(parcelableProperty, flags)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
open class BaseParcelable(parcel: Parcel) : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<BaseParcelable> {
|
||||
override fun createFromParcel(parcel: Parcel): BaseParcelable {
|
||||
return BaseParcelable(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<BaseParcelable?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class <caret>MyData {
|
||||
|
||||
val delegated by lazy { 0 }
|
||||
val readonlyField = true
|
||||
|
||||
var field1: Int = 0
|
||||
var field2: String = ""
|
||||
var field3: Long = 0
|
||||
var field4: Byte = 0
|
||||
var field5: Char = '\u0000'
|
||||
var field6: Short = 0
|
||||
var field7: Float = 0.0f
|
||||
var field8: Double = 0.0
|
||||
var field9: Boolean = false
|
||||
var field10: CharSequence = ""
|
||||
|
||||
var arrayfield1: IntArray
|
||||
var arrayfield2: Array<String>
|
||||
var arrayfield3: LongArray
|
||||
var arrayfield4: ByteArray
|
||||
var arrayfield5: CharArray
|
||||
var arrayfield6: ShortArray // No method for Short
|
||||
var arrayfield7: FloatArray
|
||||
var arrayfield8: DoubleArray
|
||||
var arrayfield9: BooleanArray
|
||||
var arrayfield10: Array<CharSequence> // No method for CharSequence
|
||||
|
||||
var goodArray: Array<BaseParcelable> = emptyArray()
|
||||
var badArray: Array<Parcelable> = emptyArray()
|
||||
|
||||
var goodList: List<BaseParcelable> = emptyList()
|
||||
var badList: List<Parcelable> = emptyList()
|
||||
|
||||
var parcelableProperty: BaseParcelable
|
||||
val uninitializedVal: Int
|
||||
|
||||
val fieldWIthGetter: Int
|
||||
get() {
|
||||
return 0
|
||||
}
|
||||
|
||||
var fieldWithCustomGetterAndSetter: Int = 0
|
||||
get() {
|
||||
return field
|
||||
}
|
||||
set(value: Int) {
|
||||
field = value
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
open class BaseParcelable(parcel: Parcel) : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<BaseParcelable> {
|
||||
override fun createFromParcel(parcel: Parcel): BaseParcelable {
|
||||
return BaseParcelable(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<BaseParcelable?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MyData() : Parcelable {
|
||||
|
||||
val delegated by lazy { 0 }
|
||||
val readonlyField = true
|
||||
|
||||
var field1: Int = 0
|
||||
var field2: String = ""
|
||||
var field3: Long = 0
|
||||
var field4: Byte = 0
|
||||
var field5: Char = '\u0000'
|
||||
var field6: Short = 0
|
||||
var field7: Float = 0.0f
|
||||
var field8: Double = 0.0
|
||||
var field9: Boolean = false
|
||||
var field10: CharSequence = ""
|
||||
|
||||
var arrayfield1: IntArray
|
||||
var arrayfield2: Array<String>
|
||||
var arrayfield3: LongArray
|
||||
var arrayfield4: ByteArray
|
||||
var arrayfield5: CharArray
|
||||
var arrayfield6: ShortArray // No method for Short
|
||||
var arrayfield7: FloatArray
|
||||
var arrayfield8: DoubleArray
|
||||
var arrayfield9: BooleanArray
|
||||
var arrayfield10: Array<CharSequence> // No method for CharSequence
|
||||
|
||||
var goodArray: Array<BaseParcelable> = emptyArray()
|
||||
var badArray: Array<Parcelable> = emptyArray()
|
||||
|
||||
var goodList: List<BaseParcelable> = emptyList()
|
||||
var badList: List<Parcelable> = emptyList()
|
||||
|
||||
var parcelableProperty: BaseParcelable
|
||||
val uninitializedVal: Int
|
||||
|
||||
val fieldWIthGetter: Int
|
||||
get() {
|
||||
return 0
|
||||
}
|
||||
|
||||
var fieldWithCustomGetterAndSetter: Int = 0
|
||||
get() {
|
||||
return field
|
||||
}
|
||||
set(value: Int) {
|
||||
field = value
|
||||
}
|
||||
|
||||
constructor(parcel: Parcel) : this() {
|
||||
field1 = parcel.readInt()
|
||||
field2 = parcel.readString()
|
||||
field3 = parcel.readLong()
|
||||
field4 = parcel.readByte()
|
||||
field5 = parcel.readInt().toChar()
|
||||
field6 = parcel.readInt().toShort()
|
||||
field7 = parcel.readFloat()
|
||||
field8 = parcel.readDouble()
|
||||
field9 = parcel.readByte() != 0.toByte()
|
||||
field10 = parcel.readString()
|
||||
arrayfield1 = parcel.createIntArray()
|
||||
arrayfield2 = parcel.createStringArray()
|
||||
arrayfield3 = parcel.createLongArray()
|
||||
arrayfield4 = parcel.createByteArray()
|
||||
arrayfield5 = parcel.createCharArray()
|
||||
arrayfield7 = parcel.createFloatArray()
|
||||
arrayfield8 = parcel.createDoubleArray()
|
||||
arrayfield9 = parcel.createBooleanArray()
|
||||
goodArray = parcel.createTypedArray(BaseParcelable)
|
||||
goodList = parcel.createTypedArrayList(BaseParcelable)
|
||||
parcelableProperty = parcel.readParcelable(BaseParcelable::class.java.classLoader)
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(field1)
|
||||
parcel.writeString(field2)
|
||||
parcel.writeLong(field3)
|
||||
parcel.writeByte(field4)
|
||||
parcel.writeInt(field5.toInt())
|
||||
parcel.writeInt(field6.toInt())
|
||||
parcel.writeFloat(field7)
|
||||
parcel.writeDouble(field8)
|
||||
parcel.writeByte(if (field9) 1 else 0)
|
||||
parcel.writeString(field10.toString())
|
||||
parcel.writeIntArray(arrayfield1)
|
||||
parcel.writeStringArray(arrayfield2)
|
||||
parcel.writeLongArray(arrayfield3)
|
||||
parcel.writeByteArray(arrayfield4)
|
||||
parcel.writeCharArray(arrayfield5)
|
||||
parcel.writeFloatArray(arrayfield7)
|
||||
parcel.writeDoubleArray(arrayfield8)
|
||||
parcel.writeBooleanArray(arrayfield9)
|
||||
parcel.writeTypedArray(goodArray, flags)
|
||||
parcel.writeTypedList(goodList)
|
||||
parcel.writeParcelable(parcelableProperty, flags)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
// NOT_AVAILABLE
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
class <caret>Simple(parcel: Parcel) : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Simple> {
|
||||
override fun createFromParcel(parcel: Parcel): Simple {
|
||||
return Simple(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Simple?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
|
||||
class <caret>MyData(val number: Int, val text: String, val flag: Boolean) {
|
||||
var count = 0
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
|
||||
class MyData(val number: Int, val text: String, val flag: Boolean) : Parcelable {
|
||||
var count = 0
|
||||
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readInt(),
|
||||
parcel.readString(),
|
||||
parcel.readByte() != 0.toByte()) {
|
||||
count = parcel.readInt()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(number)
|
||||
parcel.writeString(text)
|
||||
parcel.writeByte(if (flag) 1 else 0)
|
||||
parcel.writeInt(count)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
|
||||
class <caret>MyData(val number: Int, val text: String, flag: Boolean)
|
||||
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
|
||||
class MyData(val number: Int, val text: String, flag: Boolean) : Parcelable {
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readInt(),
|
||||
parcel.readString(),
|
||||
TODO("flag")) {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(number)
|
||||
parcel.writeString(text)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class <caret>Simple : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Simple> {
|
||||
override fun createFromParcel(parcel: Parcel): Simple {
|
||||
return Simple(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Simple?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class Simple() : Parcelable {
|
||||
constructor(parcel: Parcel) : this() {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Simple> {
|
||||
override fun createFromParcel(parcel: Parcel): Simple {
|
||||
return Simple(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Simple?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
class <caret>Simple(parcel: Parcel) : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Simple> {
|
||||
override fun createFromParcel(parcel: Parcel): Simple {
|
||||
return Simple(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Simple?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
class Simple(parcel: Parcel) : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Simple> {
|
||||
override fun createFromParcel(parcel: Parcel): Simple {
|
||||
return Simple(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Simple?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class <caret>Simple(parcel: Parcel) : Parcelable {
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Simple> {
|
||||
override fun createFromParcel(parcel: Parcel): Simple {
|
||||
return Simple(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Simple?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class Simple(parcel: Parcel) : Parcelable {
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Simple> {
|
||||
override fun createFromParcel(parcel: Parcel): Simple {
|
||||
return Simple(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Simple?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
|
||||
class <caret>Simple
|
||||
@@ -0,0 +1,27 @@
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
|
||||
class Simple() : Parcelable {
|
||||
constructor(parcel: Parcel) : this() {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Simple> {
|
||||
override fun createFromParcel(parcel: Parcel): Simple {
|
||||
return Simple(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Simple?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
// WITH_RUNTIME
|
||||
|
||||
class <caret>WithTransient() {
|
||||
@Transient var transientText: String = ""
|
||||
var text: String = ""
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.ImplementParcelableAction
|
||||
// WITH_RUNTIME
|
||||
|
||||
class WithTransient() : Parcelable {
|
||||
@Transient var transientText: String = ""
|
||||
var text: String = ""
|
||||
|
||||
constructor(parcel: Parcel) : this() {
|
||||
text = parcel.readString()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeString(text)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<WithTransient> {
|
||||
override fun createFromParcel(parcel: Parcel): WithTransient {
|
||||
return WithTransient(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<WithTransient?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
open class BaseParcelable(parcel: Parcel) : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<BaseParcelable> {
|
||||
override fun createFromParcel(parcel: Parcel): BaseParcelable {
|
||||
return BaseParcelable(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<BaseParcelable?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class <caret>MyData(prcl: Parcel) : BaseParcelable(prcl) {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
super.writeToParcel(parcel, flags)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
open class BaseParcelable(parcel: Parcel) : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<BaseParcelable> {
|
||||
override fun createFromParcel(parcel: Parcel): BaseParcelable {
|
||||
return BaseParcelable(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<BaseParcelable?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MyData() : BaseParcelable(prcl) {
|
||||
constructor(parcel: Parcel) : this() {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
super.writeToParcel(parcel, flags)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
class <caret>MyData(parcel: Parcel) : Parcelable {
|
||||
|
||||
var count: Int = 0
|
||||
var text: String = ""
|
||||
|
||||
init {
|
||||
count = parcel.readInt()
|
||||
text = parcel.readString()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(count)
|
||||
parcel.writeString(text)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
class MyData() : Parcelable {
|
||||
|
||||
var count: Int = 0
|
||||
var text: String = ""
|
||||
|
||||
constructor(parcel: Parcel) : this() {
|
||||
count = parcel.readInt()
|
||||
text = parcel.readString()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(count)
|
||||
parcel.writeString(text)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
class <caret>MyData(parcel: Parcel) : Parcelable {
|
||||
|
||||
var count: Int = 0
|
||||
var text: String = ""
|
||||
|
||||
fun initialize() {
|
||||
|
||||
}
|
||||
|
||||
init {
|
||||
initialize()
|
||||
count = parcel.readInt()
|
||||
text = parcel.readString()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(count)
|
||||
parcel.writeString(text)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
class MyData() : Parcelable {
|
||||
|
||||
var count: Int = 0
|
||||
var text: String = ""
|
||||
|
||||
constructor(parcel: Parcel) : this() {
|
||||
count = parcel.readInt()
|
||||
text = parcel.readString()
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
|
||||
}
|
||||
|
||||
init {
|
||||
initialize()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(count)
|
||||
parcel.writeString(text)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
// NOT_AVAILABLE
|
||||
|
||||
class <caret>Simple {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class <caret>SomeData(parcel: Parcel) : Parcelable {
|
||||
var count = 0
|
||||
|
||||
init {
|
||||
oldField = parcel.readInt()
|
||||
field9 = parcel.readByte() != 0.toByte()
|
||||
goodArray = parcel.createTypedArray(SuperParcelable)
|
||||
goodList = parcel.createTypedArrayList(SuperParcelable)
|
||||
parcelableProperty = parcel.readParcelable(SuperParcelable::class.java.classLoader)
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(oldField)
|
||||
parcel.writeByte(if (field9) 1 else 0)
|
||||
parcel.writeTypedArray(goodArray, flags)
|
||||
parcel.writeTypedList(goodList)
|
||||
parcel.writeParcelable(parcelableProperty, flags)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 42
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<SomeData> {
|
||||
override fun createFromParcel(parcel: Parcel): SomeData {
|
||||
return SomeData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<SomeData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class SomeData() : Parcelable {
|
||||
var count = 0
|
||||
|
||||
constructor(parcel: Parcel) : this() {
|
||||
count = parcel.readInt()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(count)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<SomeData> {
|
||||
override fun createFromParcel(parcel: Parcel): SomeData {
|
||||
return SomeData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<SomeData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class <caret>SomeData(val number: Int, val text: String, val flag: Boolean) : Parcelable {
|
||||
constructor(parcel: Parcel) : this(parcel.readString()) {
|
||||
someOtherField = parcel.readInt()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeString(oldField)
|
||||
parcel.writeInt(someOtherField)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 42
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<SomeData> {
|
||||
override fun createFromParcel(parcel: Parcel): SomeData {
|
||||
return SomeData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<SomeData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class SomeData(val number: Int, val text: String, val flag: Boolean) : Parcelable {
|
||||
constructor(parcel: Parcel) : this(
|
||||
parcel.readInt(),
|
||||
parcel.readString(),
|
||||
parcel.readByte() != 0.toByte()) {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(number)
|
||||
parcel.writeString(text)
|
||||
parcel.writeByte(if (flag) 1 else 0)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<SomeData> {
|
||||
override fun createFromParcel(parcel: Parcel): SomeData {
|
||||
return SomeData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<SomeData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
import android.os.Parcelable
|
||||
|
||||
class <caret>Simple : Parcelable
|
||||
@@ -0,0 +1,26 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RedoParcelableAction
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class Simple() : Parcelable {
|
||||
constructor(parcel: Parcel) : this() {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Simple> {
|
||||
override fun createFromParcel(parcel: Parcel): Simple {
|
||||
return Simple(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Simple?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RemoveParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
open class BaseParcelable(parcel: Parcel) : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<BaseParcelable> {
|
||||
override fun createFromParcel(parcel: Parcel): BaseParcelable {
|
||||
return BaseParcelable(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<BaseParcelable?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class <caret>MyData(parcel: Parcel) : BaseParcelable(parcel) {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
super.writeToParcel(parcel, flags)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RemoveParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
open class BaseParcelable(parcel: Parcel) : Parcelable {
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<BaseParcelable> {
|
||||
override fun createFromParcel(parcel: Parcel): BaseParcelable {
|
||||
return BaseParcelable(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<BaseParcelable?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MyData : BaseParcelable(parcel) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RemoveParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
class <caret>MyData(parcel: Parcel) : Parcelable {
|
||||
|
||||
var count: Int = 0
|
||||
var text: String = ""
|
||||
|
||||
init {
|
||||
count = parcel.readInt()
|
||||
text = parcel.readString()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(count)
|
||||
parcel.writeString(text)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RemoveParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
class MyData {
|
||||
|
||||
var count: Int = 0
|
||||
var text: String = ""
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RemoveParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
class <caret>MyData(parcel: Parcel) : Parcelable {
|
||||
|
||||
var count: Int = 0
|
||||
var text: String = ""
|
||||
|
||||
fun initialize() {
|
||||
|
||||
}
|
||||
|
||||
init {
|
||||
initialize()
|
||||
count = parcel.readInt()
|
||||
text = parcel.readString()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(count)
|
||||
parcel.writeString(text)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MyData> {
|
||||
override fun createFromParcel(parcel: Parcel): MyData {
|
||||
return MyData(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MyData?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RemoveParcelableAction
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
|
||||
class MyData {
|
||||
|
||||
var count: Int = 0
|
||||
var text: String = ""
|
||||
|
||||
fun initialize() {
|
||||
|
||||
}
|
||||
|
||||
init {
|
||||
initialize()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RemoveParcelableAction
|
||||
// NOT_AVAILABLE
|
||||
|
||||
class <caret>Simple {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RemoveParcelableAction
|
||||
import android.os.Parcelable
|
||||
|
||||
class <caret>Simple : Parcelable
|
||||
@@ -0,0 +1,4 @@
|
||||
// INTENTION_CLASS: org.jetbrains.kotlin.android.intention.RemoveParcelableAction
|
||||
import android.os.Parcelable
|
||||
|
||||
class Simple
|
||||
@@ -0,0 +1,14 @@
|
||||
// INTENTION_TEXT: Add Parcelable Implementation
|
||||
// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintParcelCreatorInspection
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class <caret>MissingCreator : Parcelable {
|
||||
override fun writeToParcel(dest: Parcel?, flags: Int) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
TODO("not implemented")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// INTENTION_TEXT: Add Parcelable Implementation
|
||||
// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintParcelCreatorInspection
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class MissingCreator() : Parcelable {
|
||||
constructor(parcel: Parcel) : this() {
|
||||
}
|
||||
|
||||
override fun writeToParcel(dest: Parcel?, flags: Int) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<MissingCreator> {
|
||||
override fun createFromParcel(parcel: Parcel): MissingCreator {
|
||||
return MissingCreator(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<MissingCreator?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// INTENTION_TEXT: Add Parcelable Implementation
|
||||
// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintParcelCreatorInspection
|
||||
import android.os.Parcelable
|
||||
|
||||
class <caret>NoImplementation : Parcelable
|
||||
@@ -0,0 +1,27 @@
|
||||
// INTENTION_TEXT: Add Parcelable Implementation
|
||||
// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintParcelCreatorInspection
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class NoImplementation() : Parcelable {
|
||||
constructor(parcel: Parcel) : this() {
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<NoImplementation> {
|
||||
override fun createFromParcel(parcel: Parcel): NoImplementation {
|
||||
return NoImplementation(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<NoImplementation?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,5 +19,6 @@
|
||||
<orderEntry type="module" module-name="idea-analysis" />
|
||||
<orderEntry type="module" module-name="idea-core" />
|
||||
<orderEntry type="module" module-name="idea" />
|
||||
<orderEntry type="module" module-name="idea-android" />
|
||||
</component>
|
||||
</module>
|
||||
+5
-1
@@ -255,7 +255,11 @@ public class AndroidLintInspectionToolProvider {
|
||||
public AndroidKLintParcelCreatorInspection() {
|
||||
super(AndroidBundle.message("android.lint.inspections.parcel.creator"), ParcelDetector.ISSUE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) {
|
||||
return new AndroidLintQuickFix[]{ new ParcelableQuickFix() };
|
||||
}
|
||||
}
|
||||
|
||||
public static class AndroidKLintPluralsCandidateInspection extends AndroidLintInspectionBase {
|
||||
|
||||
+38
@@ -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.android.inspections.klint
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.android.util.AndroidBundle
|
||||
import org.jetbrains.kotlin.android.canAddParcelable
|
||||
import org.jetbrains.kotlin.android.implementParcelable
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
|
||||
|
||||
class ParcelableQuickFix : AndroidLintQuickFix {
|
||||
override fun apply(startElement: PsiElement, endElement: PsiElement, context: AndroidQuickfixContexts.Context) {
|
||||
startElement.getTargetClass()?.implementParcelable()
|
||||
}
|
||||
|
||||
override fun isApplicable(startElement: PsiElement, endElement: PsiElement, contextType: AndroidQuickfixContexts.ContextType): Boolean =
|
||||
startElement.getTargetClass()?.canAddParcelable() ?: false
|
||||
|
||||
override fun getName(): String = AndroidBundle.message("implement.parcelable.intention.text")
|
||||
|
||||
private fun PsiElement.getTargetClass(): KtClass? = PsiTreeUtil.getParentOfType(this, KtClass::class.java, false)
|
||||
}
|
||||
Reference in New Issue
Block a user