diff --git a/value-fixture/src/org/immutables/fixture/parcelable/CustomParcelable.java b/value-fixture/src/org/immutables/fixture/parcelable/CustomParcelable.java new file mode 100644 index 000000000..18f34fcfa --- /dev/null +++ b/value-fixture/src/org/immutables/fixture/parcelable/CustomParcelable.java @@ -0,0 +1,42 @@ +/* + Copyright 2017 Immutables Authors and Contributors + + 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.immutables.fixture.parcelable; + +import android.os.Parcel; +import android.os.Parcelable; +import org.immutables.value.Value; + +// Having CREATOR field we suppress parcelable generation +@Value.Immutable +public abstract class CustomParcelable implements Parcelable { + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public CustomParcelable createFromParcel(Parcel in) { + throw new UnsupportedOperationException(); + } + + public CustomParcelable[] newArray(int size) { + throw new UnsupportedOperationException(); + } + }; + + @Override + public final int describeContents() { + return 0; + } + + @Override + public final void writeToParcel(Parcel dest, int flags) {} +} diff --git a/value-processor/src/org/immutables/value/processor/Parcelables.generator b/value-processor/src/org/immutables/value/processor/Parcelables.generator index 7b37d526b..b04da8bfc 100644 --- a/value-processor/src/org/immutables/value/processor/Parcelables.generator +++ b/value-processor/src/org/immutables/value/processor/Parcelables.generator @@ -14,7 +14,7 @@ limitations under the License. --] [template public generate Type type] -[if type.parcelable] +[if type.generateParcelable] [generateCreator type] [generateParcelableMethods type] [/if] @@ -28,11 +28,11 @@ public static final android.os.Parcelable.ClassLoaderCreator<[type.typeValue.rel public [type.typeValue.relative] createFromParcel(android.os.Parcel in) { return createFromParcel(in, this.getClass().getClassLoader()); } - + @SuppressWarnings("unchecked") [-- Guess this is needed for generic types casting --] public [type.typeValue.relative] createFromParcel(android.os.Parcel in, ClassLoader classLoader) { [generateParcelableBuild type] - } + } public [type.typeValue.relative]['[]'] newArray(int size) { return new [type.typeValue.relative]['[size]']; @@ -152,4 +152,4 @@ return [type.factoryOf.relative]([for c in type.constructorArguments][if not for [-- one liner templates are usually inlined by template compiler --] [template castBuildStagedBuilder Type type String expression][for tb = type.telescopicBuild][if tb](([type.typeBuilderImpl.relative]) [expression])[else][expression][/if][/for][/template] -[template atNullable][if classpath.available 'javax.annotation.Nullable']@javax.annotation.Nullable [/if][/template] \ No newline at end of file +[template atNullable][if classpath.available 'javax.annotation.Nullable']@javax.annotation.Nullable [/if][/template] diff --git a/value-processor/src/org/immutables/value/processor/meta/AccessorAttributesCollector.java b/value-processor/src/org/immutables/value/processor/meta/AccessorAttributesCollector.java index ee8129d4e..42c1d7dba 100644 --- a/value-processor/src/org/immutables/value/processor/meta/AccessorAttributesCollector.java +++ b/value-processor/src/org/immutables/value/processor/meta/AccessorAttributesCollector.java @@ -45,7 +45,7 @@ final class AccessorAttributesCollector { private static final String ORDINAL_ORDINAL_ATTRIBUTE_NAME = "ordinal"; private static final String ORDINAL_DOMAIN_ATTRIBUTE_NAME = "domain"; - private static final String PARCELABLE_DESCRIBE_CONTENTS_ATTRIBUTE_NAME = "describeContents"; + private static final String PARCELABLE_DESCRIBE_CONTENTS_METHOD = "describeContents"; private static final String ORG_ECLIPSE = "org.eclipse"; @@ -385,7 +385,7 @@ private AttributeNames deriveNames(String accessorName) { return styles.forAccessorWithRaw(accessorName, accessorName); } break; - case PARCELABLE_DESCRIBE_CONTENTS_ATTRIBUTE_NAME: + case PARCELABLE_DESCRIBE_CONTENTS_METHOD: if (type.isParcelable()) { return styles.forAccessorWithRaw(accessorName, accessorName); } diff --git a/value-processor/src/org/immutables/value/processor/meta/Proto.java b/value-processor/src/org/immutables/value/processor/meta/Proto.java index 50bc5c08b..08f632295 100644 --- a/value-processor/src/org/immutables/value/processor/meta/Proto.java +++ b/value-processor/src/org/immutables/value/processor/meta/Proto.java @@ -1836,4 +1836,5 @@ && isAnnotatedWith(e, annotation)) { static final String JACKSON_SERIALIZE = "com.fasterxml.jackson.databind.annotation.JsonSerialize"; static final String JACKSON_ANNOTATIONS_INSIDE = "com.fasterxml.jackson.annotation.JacksonAnnotationsInside"; static final String PARCELABLE_INTERFACE_TYPE = "android.os.Parcelable"; + static final String PARCELABLE_CREATOR_FIELD = "CREATOR"; } diff --git a/value-processor/src/org/immutables/value/processor/meta/ValueType.java b/value-processor/src/org/immutables/value/processor/meta/ValueType.java index 29e6e491f..01c150f3c 100644 --- a/value-processor/src/org/immutables/value/processor/meta/ValueType.java +++ b/value-processor/src/org/immutables/value/processor/meta/ValueType.java @@ -512,8 +512,9 @@ public boolean isGenerateWithInterface() { public boolean isUseCopyMethods() { return !getSettableAttributes().isEmpty() - && (isGenerateWithInterface() || (immutableFeatures.copy() - && !constitution.isImplementationHidden())); + && (isGenerateWithInterface() + || (immutableFeatures.copy() + && !constitution.isImplementationHidden())); } public boolean isUseCopyConstructor() { @@ -593,7 +594,7 @@ public boolean isUseSingletonOnly() { && !isUseConstructor() && getWithSettableAfterConstruction().isEmpty(); } - + public boolean isUseSingletonOnlyForConstruction() { return isUseSingleton() && !useAttributelessSingleton() @@ -915,7 +916,7 @@ public boolean hasAuxiliaryAttributes() { } return false; } - + public boolean hasSingleParameterConstructor() { return isUseConstructor() && getConstructorArguments().size() == 1; } @@ -1285,6 +1286,21 @@ void detectSerialization() { } } + private boolean hasCreatorDefined; + + void detectParcelableCreator() { + for (VariableElement v : ElementFilter.fieldsIn(element.getEnclosedElements())) { + if (v.getSimpleName().contentEquals(Proto.PARCELABLE_CREATOR_FIELD)) { + hasCreatorDefined = true; + break; + } + } + } + + public boolean isGenerateParcelable() { + return isParcelable() && !hasCreatorDefined; + } + public Set getImmutableCopyOfRoutines() { Set routines = new LinkedHashSet<>(); routines.addAll(constitution.style().immutableCopyOfRoutinesNames()); @@ -1352,8 +1368,8 @@ public ImmutableList getDocComment() { if (docComment == null) { this.docComment = constitution.isImplementationPrimary() || constitution.style().getStyles().isImmutableIdentityNaming() - ? extractDocComment(element) - : ImmutableList.of(); + ? extractDocComment(element) + : ImmutableList.of(); } return docComment; } @@ -1366,7 +1382,8 @@ public Set getNonAttributeAbstractMethodSignatures() { if (element.getKind().isClass() || element.getKind().isInterface()) { Set signatures = new LinkedHashSet<>(); - List members = constitution.protoclass().environment() + List members = constitution.protoclass() + .environment() .processing() .getElementUtils() .getAllMembers(CachingElements.getDelegate((TypeElement) element)); @@ -1381,7 +1398,8 @@ public Set getNonAttributeAbstractMethodSignatures() { if (!AccessorAttributesCollector.isEclipseImplementation(m)) { returnType = AccessorAttributesCollector.asInheritedMemberReturnType( constitution.protoclass().processing(), - CachingElements.getDelegate((TypeElement) element), m); + CachingElements.getDelegate((TypeElement) element), + m); } signatures.add(toSignature(m, returnType)); } @@ -1565,7 +1583,8 @@ public GsonTypeTokens getGsonTypeTokens() { private TypeExtractor getTypeExtractor() { if (typeExtractor == null) { this.typeExtractor = new TypeExtractor( - Proto.TYPE_FACTORY, (Parameterizable) element); + Proto.TYPE_FACTORY, + (Parameterizable) element); } return typeExtractor; } @@ -1573,7 +1592,7 @@ private TypeExtractor getTypeExtractor() { public Reporter report() { return constitution.protoclass().report(); } - + public List getDebugLines() { return constitution.protoclass().getDebugLines(); } diff --git a/value-processor/src/org/immutables/value/processor/meta/ValueTypeComposer.java b/value-processor/src/org/immutables/value/processor/meta/ValueTypeComposer.java index 0287e0033..5501fbb0e 100644 --- a/value-processor/src/org/immutables/value/processor/meta/ValueTypeComposer.java +++ b/value-processor/src/org/immutables/value/processor/meta/ValueTypeComposer.java @@ -70,6 +70,7 @@ void compose(ValueType type, Protoclass protoclass) { } type.detectSerialization(); + type.detectParcelableCreator(); } checkAttributeNamesIllegalCharacters(type);