diff --git a/generator-processor/src/org/immutables/generator/processor/Accessors.java b/generator-processor/src/org/immutables/generator/processor/Accessors.java index 1ff4a782c..212b9f210 100644 --- a/generator-processor/src/org/immutables/generator/processor/Accessors.java +++ b/generator-processor/src/org/immutables/generator/processor/Accessors.java @@ -75,10 +75,10 @@ public ImmutableMap load(String key) throws Exception { }; ImmutableMap definedBy(TypeMirror type) { - if (!(type instanceof DeclaredType)) { - return ImmutableMap.of(); + if (type.getKind() == TypeKind.DECLARED) { + return accessorsDefined.get(toName(type)); } - return accessorsDefined.get(toName(type)); + return ImmutableMap.of(); } private ImmutableMap extractFrom(@Nullable TypeElement type) { @@ -230,7 +230,7 @@ public boolean isContainer() { @Nullable private TypeMirror inferContainedType(TypeMirror type) { - if (type instanceof DeclaredType) { + if (type.getKind() == TypeKind.DECLARED) { DeclaredType declaredType = (DeclaredType) type; if (isIterableType(declaredType) || isOptionalType(declaredType)) { // TBD wrong logic to unpack, need to create super utility for introspecting type diff --git a/generator-processor/src/org/immutables/generator/processor/Implicits.java b/generator-processor/src/org/immutables/generator/processor/Implicits.java index 29d8bada0..065b3ba4f 100644 --- a/generator-processor/src/org/immutables/generator/processor/Implicits.java +++ b/generator-processor/src/org/immutables/generator/processor/Implicits.java @@ -15,6 +15,7 @@ */ package org.immutables.generator.processor; +import javax.lang.model.type.TypeKind; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.Iterables; import com.google.common.collect.ListMultimap; @@ -76,7 +77,7 @@ public interface ImplicitResolver { } private DeclaredType checkDeclaredType(TypeMirror type) { - checkState(type instanceof DeclaredType, "'%s' should have been a declared type", type); + checkState(type.getKind() == TypeKind.DECLARED, "'%s' should have been a declared type", type); return (DeclaredType) type; } } diff --git a/generator-processor/src/org/immutables/generator/processor/Imports.java b/generator-processor/src/org/immutables/generator/processor/Imports.java index 18c2bb2be..d4bd86b6e 100644 --- a/generator-processor/src/org/immutables/generator/processor/Imports.java +++ b/generator-processor/src/org/immutables/generator/processor/Imports.java @@ -100,7 +100,7 @@ private boolean shouldConsideredAsTypeUsage(ExecutableElement method) { } private void collectIfSimpleType(TypeMirror type, Map collected) { - if (type instanceof DeclaredType) { + if (type.getKind() == TypeKind.DECLARED) { DeclaredType declared = (DeclaredType) type; if (declared.getTypeArguments().isEmpty()) { collected.put(declared.asElement().getSimpleName().toString(), declared); diff --git a/generator/src/org/immutables/generator/SourceOrdering.java b/generator/src/org/immutables/generator/SourceOrdering.java index 86def8076..8888fa2a8 100644 --- a/generator/src/org/immutables/generator/SourceOrdering.java +++ b/generator/src/org/immutables/generator/SourceOrdering.java @@ -15,6 +15,7 @@ */ package org.immutables.generator; +import javax.lang.model.type.TypeKind; import javax.lang.model.util.Types; import com.google.common.base.Function; import com.google.common.base.Functions; @@ -207,7 +208,7 @@ void traverse(@Nullable TypeElement element) { @Nullable TypeElement asTypeElement(TypeMirror type) { - if (type instanceof DeclaredType) { + if (type.getKind() == TypeKind.DECLARED) { return (TypeElement) ((DeclaredType) type).asElement(); } return null; diff --git a/gson/test/org/immutables/gson/adapter/AbstractStylee.java b/gson/test/org/immutables/gson/adapter/AbstractStylee.java new file mode 100644 index 000000000..cccd866bf --- /dev/null +++ b/gson/test/org/immutables/gson/adapter/AbstractStylee.java @@ -0,0 +1,69 @@ +/* + Copyright 2015 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.gson.adapter; + +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Multiset; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.immutables.gson.Gson; +import org.immutables.value.Value; +import org.immutables.value.Value.Style.ImplementationVisibility; + +/** + * Compilation test on customized by style value + */ +@Value.Immutable(builder = false) +@Value.Enclosing +@Gson.TypeAdapters +@Value.Style( + typeAbstract = "I*", + typeImmutable = "*", + init = "set*", + add = "push*", + addAll = "pushAll*", + put = "push*", + putAll = "pushAll*", + builder = "new", + build = "create", + visibility = ImplementationVisibility.PUBLIC) +interface IStylee { + + @Value.Parameter + Set getSet(); + + @Value.Parameter + Multiset getBag(); + + @Value.Immutable + interface IInr { + String[] getArr(); + + List getList(); + + Map getMap(); + + ListMultimap getListMultimap(); + } + + @Value.Immutable + interface INst { + int getValue(); + + String getString(); + } +} diff --git a/gson/test/org/immutables/gson/adapter/AdaptReadWriteTest.java b/gson/test/org/immutables/gson/adapter/AdaptReadWriteTest.java index 5d6e4588a..8a1a6eefb 100644 --- a/gson/test/org/immutables/gson/adapter/AdaptReadWriteTest.java +++ b/gson/test/org/immutables/gson/adapter/AdaptReadWriteTest.java @@ -25,6 +25,7 @@ public class AdaptReadWriteTest { private final Gson gson = new GsonBuilder() .registerTypeAdapterFactory(new GsonAdaptersAdapt()) + .registerTypeAdapterFactory(new GsonAdaptersIStylee()) .create(); private final Adapt adapt = @@ -94,4 +95,11 @@ public void adapt() { Adapt instance = gson.fromJson(json, Adapt.class); check(instance).is(adapt); } + + @Test + public void stylee() { + String json = gson.toJson(adapt); + Stylee instance = gson.fromJson(json, Stylee.class); + check(gson.fromJson(gson.toJson(instance), Stylee.class)).is(instance); + } } diff --git a/value-processor/src/org/immutables/value/processor/Immutables.generator b/value-processor/src/org/immutables/value/processor/Immutables.generator index 5c90d0dcc..375ba95ff 100644 --- a/value-processor/src/org/immutables/value/processor/Immutables.generator +++ b/value-processor/src/org/immutables/value/processor/Immutables.generator @@ -105,7 +105,7 @@ import java.lang.String; [generateConstructionAndInterning type] [generateImmutableCopyOf type] [if type.useBuilder and (not type.constitution.isOutsideBuilder)] - [if type.factoryBuilder.applied ne 'new'] + [if not type.factoryBuilder.isNew] /** * Creates builder for {@link [type.typeValue]}. @@ -421,7 +421,7 @@ private Object readResolve() throws java.io.ObjectStreamException { [if type.generateOrdinalValue] private Domain domain = Domain.get(); [/if] -[for Boolean useFactoryMethod = type.factoryBuilder.applied ne 'new'] +[for Boolean useFactoryMethod = not type.factoryBuilder.isNew] [if type.kind.isFactory] [for parameters = p for p in setters if p.isBuilderParameter] diff --git a/value-processor/src/org/immutables/value/processor/meta/Constitution.java b/value-processor/src/org/immutables/value/processor/meta/Constitution.java index 7501d5dda..c23eef1c1 100644 --- a/value-processor/src/org/immutables/value/processor/meta/Constitution.java +++ b/value-processor/src/org/immutables/value/processor/meta/Constitution.java @@ -25,6 +25,7 @@ import org.immutables.generator.Naming; import org.immutables.generator.Naming.Preference; import org.immutables.value.Value; +import org.immutables.value.processor.meta.Proto.DeclaringType; import org.immutables.value.processor.meta.Proto.Protoclass; import org.immutables.value.processor.meta.Styles.UsingName.TypeNames; import static com.google.common.base.Verify.*; @@ -35,7 +36,7 @@ public abstract class Constitution { private static final String NA_ERROR = "!should_not_be_used_in_generated_code!"; private static final String NEW_KEYWORD = "new"; private static final String BUILDER_CLASS_NAME = "Builder"; - private static final Joiner JOINER = Joiner.on('.').skipNulls(); + private static final Joiner DOT_JOINER = Joiner.on('.').skipNulls(); public abstract Protoclass protoclass(); @@ -130,11 +131,11 @@ public NameForms typeAbstract() { verify(e instanceof PackageElement); String packageOf = ((PackageElement) e).getQualifiedName().toString(); - String relative = JOINER.join(classSegments); + String relative = DOT_JOINER.join(classSegments); boolean relativeAlreadyQualified = false; if (!protoclass().packageOf().name().equals(packageOf)) { - relative = JOINER.join(packageOf, relative); + relative = DOT_JOINER.join(packageOf, relative); relativeAlreadyQualified = true; } @@ -158,7 +159,7 @@ public StyleMirror style() { * @return */ private String inPackage(String topLevel, String... nested) { - return JOINER.join(null, topLevel, (Object[]) nested); + return DOT_JOINER.join(null, topLevel, (Object[]) nested); } /** @@ -196,9 +197,16 @@ public NameForms typeImmutable() { */ @Value.Lazy String typeImmutableEnclosingSimpleName() { - String enclosingSimpleName = protoclass().enclosingOf().get().element().getSimpleName().toString(); + DeclaringType declaringType = protoclass().enclosingOf().get(); + String enclosingSimpleName = declaringType.element().getSimpleName().toString(); String enclosingRawName = names().rawFromAbstract(enclosingSimpleName); - return names().namings.typeImmutableEnclosing.apply(enclosingRawName); + // Here we checking for having both enclosing and value + // if we had protoclass it would be kind().isEnclosing() && kind().isValue() + Naming naming = declaringType.isImmutable() + ? names().namings.typeImmutable + : names().namings.typeImmutableEnclosing; + + return naming.apply(enclosingRawName); } private String typeBuilderSimpleName() { @@ -217,7 +225,7 @@ private String typeBuilderSimpleName() { } @Value.Lazy - public NameForms factoryBuilder() { + public AppliedNameForms factoryBuilder() { boolean isOutside = isImplementationHidden() || isFactory(); Naming methodBuilderNaming = isOutside ? names().namings.newBuilder() @@ -240,7 +248,7 @@ private boolean isConstantNamingEquals(Naming naming, String name) { } @Value.Lazy - public NameForms factoryOf() { + public AppliedNameForms factoryOf() { if (isFactory()) { return ImmutableConstitution.NameForms.builder() .simple(protoclass().declaringType().get().element().getSimpleName().toString()) @@ -255,16 +263,16 @@ public NameForms factoryOf() { } @Value.Lazy - public NameForms factoryInstance() { + public AppliedNameForms factoryInstance() { return applyFactoryNaming(names().namings.instance); } @Value.Lazy - public NameForms factoryCopyOf() { + public AppliedNameForms factoryCopyOf() { return applyFactoryNaming(names().namings.copyOf); } - private NameForms applyFactoryNaming(Naming naming) { + private AppliedNameForms applyFactoryNaming(Naming naming) { String raw = names().raw; boolean hasForwardingFactoryMethods = isImplementationHidden() @@ -296,9 +304,13 @@ public NameForms typeEnclosingFactory() { @Value.Lazy public NameForms typeEnclosing() { + String name = protoclass().kind().isDefinedValue() + ? names().typeImmutable + : names().typeImmutableEnclosing; + return ImmutableConstitution.NameForms.builder() - .simple(names().typeImmutableEnclosing) - .relative(names().typeImmutableEnclosing) + .simple(name) + .relative(name) .packageOf(protoclass().packageOf().name()) .visibility(protoclass().declaringVisibility()) .build(); @@ -332,6 +344,58 @@ public NameForms typeBuilder() { .build(); } + @Value.Immutable + public static abstract class AppliedNameForms extends NameForms { + public abstract NameForms forms(); + + public abstract String applied(); + + @Override + @Value.Derived + public String simple() { + return isNew() + ? (NEW_KEYWORD + ' ' + forms().simple()) + : applied(); + } + + @Override + public String relative() { + return isNew() + ? (NEW_KEYWORD + ' ' + forms().relative()) + : (forms().relative() + '.' + applied()); + } + + @Value.Derived + public boolean isNew() { + return NEW_KEYWORD.equals(applied()); + } + + @Override + public String toString() { + if (relativeAlreadyQualified()) { + return relative(); + } + return isNew() + ? (NEW_KEYWORD + ' ' + qualifyWithPackage(forms().relative())) + : qualifyWithPackage(relative()); + } + + @Override + public String packageOf() { + return forms().packageOf(); + } + + @Override + public Visibility visibility() { + return forms().visibility(); + } + + @Override + public boolean relativeAlreadyQualified() { + return forms().relativeAlreadyQualified(); + } + } + @Value.Immutable public static abstract class NameForms { private static final String PUBLIC_MODIFIER_PREFIX = "public "; @@ -350,11 +414,6 @@ public boolean relativeAlreadyQualified() { return false; } - @Value.Default - public String applied() { - return ""; - } - /** * Access prefix. Includes trailing space separator if not empty (package private). * @return access keyword text @@ -370,36 +429,25 @@ public String access() { } } - public NameForms applied(String input) { - return ImmutableConstitution.NameForms.builder() - .packageOf(packageOf()) + public AppliedNameForms applied(String input) { + return ImmutableConstitution.AppliedNameForms.builder() + .forms(this) .applied(input) - .simple(applyTo(simple(), input, false)) - .relative(applyTo(relative(), input, true)) - .visibility(visibility()) - .relativeAlreadyQualified(relativeAlreadyQualified()) .build(); } - private String applyTo(String targetType, String input, boolean relative) { - return NEW_KEYWORD.equals(input) - ? (NEW_KEYWORD + ' ' + targetType) - : (relative ? targetType + '.' + input : input); - } - /** * Fully qualified type name */ @Override public String toString() { - if (relativeAlreadyQualified()) { - return relative(); - } - return qualifyWithPackage(relative()); + return relativeAlreadyQualified() + ? relative() + : qualifyWithPackage(relative()); } - private String qualifyWithPackage(String reference) { - return JOINER.join(Strings.emptyToNull(packageOf()), reference); + protected String qualifyWithPackage(String reference) { + return DOT_JOINER.join(Strings.emptyToNull(packageOf()), reference); } } } diff --git a/value-processor/src/org/immutables/value/processor/meta/ValueAttribute.java b/value-processor/src/org/immutables/value/processor/meta/ValueAttribute.java index 4d2444e32..72a3b448e 100644 --- a/value-processor/src/org/immutables/value/processor/meta/ValueAttribute.java +++ b/value-processor/src/org/immutables/value/processor/meta/ValueAttribute.java @@ -402,7 +402,7 @@ public String getElementType() { public List getExpectedSubtypes() { if (expectedSubtypes == null) { ensureTypeIntrospected(); - if (!isPrimitiveElement()) { + if (containedTypeElement != null || containedSecondaryTypeElement != null) { TypeElement supertypeElement = MoreObjects.firstNonNull(containedSecondaryTypeElement, containedTypeElement); Optional annotationOnAttribute = ExpectedSubtypesMirror.find(element); if (annotationOnAttribute.isPresent()) { @@ -484,7 +484,7 @@ protected void introspectType() { if (!typeArguments.isEmpty()) { if (typeArguments.size() == 1) { final TypeMirror typeArgument = typeArguments.get(0); - if (typeArgument instanceof DeclaredType) { + if (typeArgument.getKind() == TypeKind.DECLARED) { typeMirror = typeArgument; } @@ -500,7 +500,7 @@ protected TypeMirror internalTypeMirror() { if (typeArguments.size() >= 1) { TypeMirror typeArgument = typeArguments.get(0); - if (typeArgument instanceof DeclaredType) { + if (typeArgument.getKind() == TypeKind.DECLARED) { TypeElement typeElement = (TypeElement) ((DeclaredType) typeArgument).asElement(); hasEnumFirstTypeParameter = typeElement.getSuperclass().toString().startsWith(Enum.class.getName()); } @@ -508,7 +508,7 @@ protected TypeMirror internalTypeMirror() { if (typeArguments.size() >= 2) { TypeMirror typeSecondArgument = typeArguments.get(1); - if (typeSecondArgument instanceof DeclaredType) { + if (typeSecondArgument.getKind() == TypeKind.DECLARED) { TypeElement typeElement = (TypeElement) ((DeclaredType) typeSecondArgument).asElement(); this.containedSecondaryTypeElement = typeElement; } 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 4c2f8bcaf..0e28be0d8 100644 --- a/value-processor/src/org/immutables/value/processor/meta/ValueType.java +++ b/value-processor/src/org/immutables/value/processor/meta/ValueType.java @@ -15,6 +15,7 @@ */ package org.immutables.value.processor.meta; +import org.immutables.value.processor.meta.Constitution.AppliedNameForms; import javax.lang.model.type.TypeKind; import javax.lang.model.element.VariableElement; import javax.lang.model.util.ElementFilter; @@ -86,19 +87,19 @@ public TypeNames names() { return constitution.names(); } - public NameForms factoryOf() { + public AppliedNameForms factoryOf() { return constitution.factoryOf(); } - public NameForms factoryCopyOf() { + public AppliedNameForms factoryCopyOf() { return constitution.factoryCopyOf(); } - public NameForms factoryInstance() { + public AppliedNameForms factoryInstance() { return constitution.factoryInstance(); } - public NameForms factoryBuilder() { + public AppliedNameForms factoryBuilder() { return constitution.factoryBuilder(); }