diff --git a/builder/pom.xml b/builder/pom.xml index 9414d26df..f29373b3c 100644 --- a/builder/pom.xml +++ b/builder/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 immutables @@ -22,11 +23,20 @@ ${project.version} test + org.immutables - value + value-annotations ${project.version} + provided true + + org.immutables + value-processor + ${project.version} + test + diff --git a/generator/src/org/immutables/generator/Output.java b/generator/src/org/immutables/generator/Output.java index 62c11e837..7033bea9a 100644 --- a/generator/src/org/immutables/generator/Output.java +++ b/generator/src/org/immutables/generator/Output.java @@ -297,12 +297,12 @@ void complete() { writer.append(sourceCode); } } catch (FilerException ex) { - if (!identicalFileIsAlreadyGenerated(sourceCode)) { - getMessager().printMessage(Kind.ERROR, - "Generated source file name collission. Attempt to overwrite already generated file: " + key); + if (identicalFileIsAlreadyGenerated(sourceCode)) { + getMessager().printMessage(Kind.MANDATORY_WARNING, "Regenerated file with the same content: " + key); } else { - getMessager().printMessage(Kind.MANDATORY_WARNING, - "Regenerated file with the same content: " + key); + getMessager().printMessage(Kind.ERROR, String.format( + "Generated source file name collission. Attempt to overwrite already generated file: %s, %s", + key, ex)); } } catch (IOException ex) { throw Throwables.propagate(ex); @@ -312,10 +312,14 @@ void complete() { private boolean identicalFileIsAlreadyGenerated(CharSequence sourceCode) { try { String existingContent = new CharSource() { + final String packagePath = !key.packageName.isEmpty() ? (key.packageName.replace('.', '/') + '/') : ""; + final String filename = key.relativeName + ".java"; + @Override public Reader openStream() throws IOException { return getFiler() - .getResource(StandardLocation.SOURCE_OUTPUT, key.packageName, key.relativeName) + .getResource(StandardLocation.SOURCE_OUTPUT, + "", packagePath + filename) .openReader(true); } }.read(); diff --git a/gson/pom.xml b/gson/pom.xml index a39135ef2..1759f57d3 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -57,14 +57,24 @@ 2.0 true + + + + org.immutables + value-annotations + ${project.version} + provided + true + - org.immutables - value + value-processor ${project.version} provided true + org.immutables diff --git a/mongo/pom.xml b/mongo/pom.xml index 8ff8d0ed3..38a43f820 100644 --- a/mongo/pom.xml +++ b/mongo/pom.xml @@ -29,14 +29,21 @@ pom + - org.immutables - value + value-annotations ${project.version} test true + + org.immutables + value-processor + ${project.version} + test + diff --git a/mongo/test/org/immutables/mongo/fixture/sub/Item2.java b/mongo/test/org/immutables/mongo/fixture/sub/Item2.java index fa1b2cc97..29a61f318 100644 --- a/mongo/test/org/immutables/mongo/fixture/sub/Item2.java +++ b/mongo/test/org/immutables/mongo/fixture/sub/Item2.java @@ -16,13 +16,10 @@ package org.immutables.mongo.fixture.sub; import java.util.List; -import java.util.Set; +import org.immutables.gson.Gson; import org.immutables.mongo.Mongo; -import org.immutables.mongo.types.Binary; -import org.immutables.mongo.types.Id; -import org.immutables.value.Value; import org.immutables.mongo.fixture.*; -import org.immutables.gson.Gson; +import org.immutables.value.Value; @Mongo.Repository @Value.Immutable diff --git a/ordinal/pom.xml b/ordinal/pom.xml index 4ea84cda4..7e4675d5d 100644 --- a/ordinal/pom.xml +++ b/ordinal/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 immutables @@ -28,9 +29,17 @@ ${project.version} test + org.immutables - value + value-annotations + ${project.version} + test + + + org.immutables + value-processor ${project.version} test diff --git a/pom.xml b/pom.xml index b10b56fce..b42401acf 100644 --- a/pom.xml +++ b/pom.xml @@ -106,11 +106,12 @@ org.apache.maven.plugins maven-compiler-plugin - 3.1 + 3.3 1.7 1.7 1.7 + false -Xlint:unchecked diff --git a/value-fixture/pom.xml b/value-fixture/pom.xml index 3e1d37a25..63231acb5 100644 --- a/value-fixture/pom.xml +++ b/value-fixture/pom.xml @@ -15,11 +15,21 @@ + org.immutables - value + value-annotations ${project.version} + true + + org.immutables + value-processor + ${project.version} + true + + org.immutables gson 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 c23eef1c1..ad6f73fed 100644 --- a/value-processor/src/org/immutables/value/processor/meta/Constitution.java +++ b/value-processor/src/org/immutables/value/processor/meta/Constitution.java @@ -148,7 +148,7 @@ public NameForms typeAbstract() { .build(); } - public StyleMirror style() { + public StyleInfo style() { return protoclass().styles().style(); } 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 4c05564ab..58a397db1 100644 --- a/value-processor/src/org/immutables/value/processor/meta/Proto.java +++ b/value-processor/src/org/immutables/value/processor/meta/Proto.java @@ -54,8 +54,8 @@ public static abstract class MetaAnnotated { @Value.Derived @Value.Auxiliary - public Optional style() { - return StyleMirror.find(element()); + public Optional style() { + return StyleMirror.find(element()).transform(ToStyleInfo.FUNCTION); } public static MetaAnnotated from(AnnotationMirror mirror) { @@ -99,12 +99,12 @@ abstract static class Environment { abstract Round round(); @Value.Derived - StyleMirror defaultStyles() { + StyleInfo defaultStyles() { TypeElement typeElement = processing() .getElementUtils() .getTypeElement(StyleMirror.qualifiedName()); - return StyleMirror.from(typeElement); + return ToStyleInfo.FUNCTION.apply(StyleMirror.from(typeElement)); } /** @@ -185,8 +185,8 @@ public List includedTypes() { } @Value.Lazy - public Optional style() { - Optional style = StyleMirror.find(element()); + public Optional style() { + Optional style = StyleMirror.find(element()).transform(ToStyleInfo.FUNCTION); if (style.isPresent()) { return style; @@ -194,7 +194,7 @@ public Optional style() { for (AnnotationMirror mirror : element().getAnnotationMirrors()) { MetaAnnotated metaAnnotated = MetaAnnotated.from(mirror); - Optional metaStyle = metaAnnotated.style(); + Optional metaStyle = metaAnnotated.style(); if (metaStyle.isPresent()) { return metaStyle; } @@ -285,8 +285,8 @@ Optional namedParentPackage() { @Override @Value.Lazy - public Optional style() { - Optional style = super.style(); + public Optional style() { + Optional style = super.style(); if (style.isPresent()) { return style; } @@ -365,15 +365,15 @@ public DeclaringPackage packageOf() { } @Value.Lazy - public Optional features() { - return ImmutableMirror.find(element()); + public Optional features() { + return ImmutableMirror.find(element()).transform(ToImmutableInfo.FUNCTION); } @Value.Lazy public boolean useImmutableDefaults() { - Optional immutables = features(); + Optional immutables = features(); if (immutables.isPresent()) { - return immutables.get().getAnnotationMirror().getElementValues().isEmpty(); + return immutables.get().isDefault(); } return true; } @@ -580,10 +580,10 @@ public Element element() { } @Value.Lazy - public ImmutableMirror features() { + public ValueImmutableInfo features() { if (declaringType().isPresent() && !declaringType().get().useImmutableDefaults()) { - Optional features = declaringType().get().features(); + Optional features = declaringType().get().features(); if (features.isPresent()) { return features.get(); } @@ -593,27 +593,27 @@ public ImmutableMirror features() { @Value.Lazy public Styles styles() { - return Styles.using(determineStyle().or(environment().defaultStyles())); + return determineStyle().or(environment().defaultStyles()).getStyles(); } - private Optional determineStyle() { + private Optional determineStyle() { if (declaringType().isPresent()) { DeclaringType type = declaringType().get(); Optional enclosing = type.enclosingOf(); if (enclosing.isPresent()) { if (enclosing.get() != type) { - Optional style = type.style(); + Optional style = type.style(); if (style.isPresent()) { warnAboutIncompatibleStyles(); } } - Optional enclosingStyle = enclosing.get().style(); + Optional enclosingStyle = enclosing.get().style(); if (enclosingStyle.isPresent()) { return enclosingStyle; } } else { - Optional style = type.style(); + Optional style = type.style(); if (style.isPresent()) { return style; } @@ -767,4 +767,48 @@ public boolean apply(Element input) { return input.getModifiers().contains(Modifier.PUBLIC); } } + + enum ToImmutableInfo implements Function { + FUNCTION; + @Override + public ValueImmutableInfo apply(ImmutableMirror input) { + return ImmutableValueImmutableInfo.theOf( + input.builder(), + input.copy(), + input.intern(), + input.prehash(), + input.singleton()) + .withIsDefault(input.getAnnotationMirror().getElementValues().isEmpty()); + } + } + + enum ToStyleInfo implements Function { + FUNCTION; + @Override + public StyleInfo apply(StyleMirror input) { + return ImmutableStyleInfo.of(input.get(), + input.init(), + input.with(), + input.add(), + input.addAll(), + input.put(), + input.putAll(), + input.copyOf(), + input.of(), + input.instance(), + input.builder(), + input.newBuilder(), + input.from(), + input.build(), + input.typeBuilder(), + input.typeAbstract(), + input.typeImmutable(), + input.typeImmutableEnclosing(), + input.typeImmutableNested(), + ToImmutableInfo.FUNCTION.apply(input.defaults()), + input.strictBuilder(), + input.visibility(), + input.jdkOnly()); + } + } } diff --git a/value-processor/src/org/immutables/value/processor/meta/StyleInfo.java b/value-processor/src/org/immutables/value/processor/meta/StyleInfo.java new file mode 100644 index 000000000..8aad47aa2 --- /dev/null +++ b/value-processor/src/org/immutables/value/processor/meta/StyleInfo.java @@ -0,0 +1,243 @@ +/* + 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.value.processor.meta; + +import java.lang.annotation.Annotation; +import org.immutables.value.Value; +import org.immutables.value.Value.Immutable; +import org.immutables.value.processor.meta.ValueMirrors.Enclosing; + +@SuppressWarnings("all") +@Value.Immutable(intern = true, copy = false, builder = false) +public abstract class StyleInfo implements ValueMirrors.Style { + + @Override + public Class annotationType() { + return ValueMirrors.Style.class; + } + + /** + * Patterns to recognize accessors. + * @return naming template + */ + @Override + @Value.Parameter + public abstract String[] get(); + + /** + * Builder initialization method. i.e. "setter" in builder. + * @return naming template + */ + @Value.Parameter + @Override + public abstract String init(); + + /** + * Modify-by-copy "with" method. + * @return naming template + */ + @Value.Parameter + @Override + public abstract String with(); + + /** + * Add value to collection attribute from iterable + * @return naming template + */ + @Value.Parameter + @Override + public abstract String add(); + + /** + * Add all values to collection attribute from iterable + * @return naming template + */ + @Value.Parameter + @Override + public abstract String addAll(); + + /** + * Puts entry to a map attribute + * @return naming template + */ + @Value.Parameter + @Override + public abstract String put(); + + /** + * Puts all entries to a map attribute + * @return naming template + */ + @Value.Parameter + @Override + public abstract String putAll(); + + /** + * Copy constructor method name. + * @return naming template + */ + @Value.Parameter + @Override + public abstract String copyOf(); + + /** + * Constructor method name. + * @return naming template + */ + @Value.Parameter + @Override + public abstract String of(); + + /** + * Singleton accessor method name + * @return naming template + */ + @Value.Parameter + @Override + public abstract String instance(); + + /** + * Builder creator method. This naming allow special keyword "new" value. + * This will customize builder to be created using constructor rather than + * factory method. + * @return naming template + */ + @Value.Parameter + @Override + public abstract String builder(); + + /** + * Builder creator method, it differes from {@link #builder()} in that this naming is used for + * builders that are external to immutable objects, such as top level builders for values or + * factories. This naming allow special keyword "new" value, which is the default. + * "new" will customize builder to be created using constructor rather than + * factory method. + * @return naming template + */ + @Value.Parameter + @Override + public abstract String newBuilder(); + + /** + * Method to initialize builder with values from instance. + * @return naming template + */ + @Value.Parameter + @Override + public abstract String from(); + + /** + * Instance creation method on builder. + * @return naming template + */ + @Value.Parameter + @Override + public abstract String build(); + + /** + * Builder class name. + * @return naming template + */ + @Value.Parameter + @Override + public abstract String typeBuilder(); + + /** + * Naming templates to detect base/raw type name from provided abstract value type name. + * @return naming templates + */ + @Value.Parameter + @Override + public abstract String[] typeAbstract(); + + /** + * Modifiable type name template. + * @return naming template + */ + @Value.Parameter + @Override + public abstract String typeImmutable(); + + /** + * Umbrella nesting class name generated using {@link Enclosing}. + * @return naming template + */ + @Value.Parameter + @Override + public abstract String typeImmutableEnclosing(); + + /** + * Immutable class name when generated under umbrella class using {@link Enclosing} annotation. + * @see #typeImmutable() + * @see #typeImmutableEnclosing() + * @return naming template + */ + @Value.Parameter + @Override + public abstract String typeImmutableNested(); + + /** + * Specify default options for the generated immutable objects. + * If at least one attribute is specifid in inline {@literal @}{@link Immutable} annotation, + * then this default will not be taken into account, objects will be generated using attributes + * from inline annotation. + * @return default configuration + */ + @Override + @Value.Parameter + public abstract ValueImmutableInfo defaults(); + + /** + * When {@code true} — forces to generate strict builder code. Strict builders are forward + * only. For collections and maps, there's no set/reset methods are generated in + * favor of using additive only initializers. For regular attributes, initializers could be + * called only once, subsequent reinitialization with throw exception. Usage of strict builders + * may help to prevent initialization mistakes. + * @return if strict builder enabled + */ + @Value.Parameter + @Override + public abstract boolean strictBuilder(); + + /** + * Specify the mode in which accibility visibility is derived from abstract value type. + * It is a good idea to not specify such attributea inline with immutable values, but rather + * create style annotation (@see Style). + * @return implementation visibility + */ + @Value.Parameter + @Override + public abstract ImplementationVisibility visibility(); + + /** + * When {@code true} — forces to generate code which use only JDK 7+ standard library + * classes. It is {@code false} by default, however usage of JDK-only classes will be turned on + * automatically if Google Guava library is not found in classpath. The generated code + * will have subtle differences, but nevertheless will be functionally equivalent. + *

+ * Note that some additional annotation processors may not work without + * Guava being accessible to the generated classes + * @return if forced JDK-only class usage + */ + @Value.Parameter + @Override + public abstract boolean jdkOnly(); + + @Value.Lazy + public Styles getStyles() { + return new Styles(this); + } +} diff --git a/value-processor/src/org/immutables/value/processor/meta/Styles.java b/value-processor/src/org/immutables/value/processor/meta/Styles.java index faa75ffec..f560442cd 100644 --- a/value-processor/src/org/immutables/value/processor/meta/Styles.java +++ b/value-processor/src/org/immutables/value/processor/meta/Styles.java @@ -16,39 +16,22 @@ package org.immutables.value.processor.meta; import com.google.common.base.CaseFormat; -import com.google.common.collect.Maps; -import java.util.Map; -import javax.annotation.concurrent.GuardedBy; import org.immutables.generator.Naming; public final class Styles { - @GuardedBy("cache") - private static final Map cache = Maps.newHashMap(); - - public static Styles using(StyleMirror style) { - synchronized (cache) { - Styles namings = cache.get(style); - if (namings == null) { - namings = new Styles(style); - cache.put(style, namings); - } - return namings; - } - } - - private final StyleMirror style; + private final StyleInfo style; private final Scheme scheme; - private Styles(StyleMirror style) { + Styles(StyleInfo style) { this.style = style; this.scheme = new Scheme(); } - public ImmutableMirror defaults() { + public ValueImmutableInfo defaults() { return style.defaults(); } - public StyleMirror style() { + public StyleInfo style() { return style; } diff --git a/value-processor/src/org/immutables/value/processor/meta/ValueImmutableInfo.java b/value-processor/src/org/immutables/value/processor/meta/ValueImmutableInfo.java new file mode 100644 index 000000000..b59042190 --- /dev/null +++ b/value-processor/src/org/immutables/value/processor/meta/ValueImmutableInfo.java @@ -0,0 +1,54 @@ +/* + 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.value.processor.meta; + +import java.lang.annotation.Annotation; +import org.immutables.value.Value; + +@SuppressWarnings("all") +@Value.Style(copyOf = "theCopyOf", of = "theOf", builder = "theBuilder") +@Value.Immutable(intern = true) +public abstract class ValueImmutableInfo implements ValueMirrors.Immutable { + @Override + public Class annotationType() { + return ValueMirrors.Immutable.class; + } + + @Value.Default + public boolean isDefault() { + return false; + } + + @Value.Parameter + @Override + public abstract boolean builder(); + + @Value.Parameter + @Override + public abstract boolean copy(); + + @Value.Parameter + @Override + public abstract boolean intern(); + + @Value.Parameter + @Override + public abstract boolean prehash(); + + @Value.Parameter + @Override + public abstract boolean singleton(); +} diff --git a/value-processor/src/org/immutables/value/processor/meta/ValueMirrors.java b/value-processor/src/org/immutables/value/processor/meta/ValueMirrors.java index 831bd07fa..7861b9ccc 100644 --- a/value-processor/src/org/immutables/value/processor/meta/ValueMirrors.java +++ b/value-processor/src/org/immutables/value/processor/meta/ValueMirrors.java @@ -20,7 +20,7 @@ public final class ValueMirrors { private ValueMirrors() {} - + @Mirror.Annotation("org.immutables.value.Value") public @interface ValueUmbrella {} 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 82c1ec163..6c67269bd 100644 --- a/value-processor/src/org/immutables/value/processor/meta/ValueType.java +++ b/value-processor/src/org/immutables/value/processor/meta/ValueType.java @@ -15,9 +15,6 @@ */ package org.immutables.value.processor.meta; -import static com.google.common.base.MoreObjects.*; -import com.google.common.base.MoreObjects; -import org.immutables.generator.SourceExtraction; import com.google.common.base.CaseFormat; import com.google.common.base.Function; import com.google.common.base.Optional; @@ -47,6 +44,7 @@ import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; +import org.immutables.generator.SourceExtraction; import org.immutables.generator.TypeHierarchyCollector; import org.immutables.value.processor.meta.Constitution.AppliedNameForms; import org.immutables.value.processor.meta.Constitution.NameForms; @@ -273,7 +271,7 @@ public boolean isUseConstructorOnly() { return isUseConstructor() && !isUseBuilder(); } - public ImmutableMirror immutableFeatures; + public ValueImmutableInfo immutableFeatures; public boolean isUseCopyMethods() { return immutableFeatures.copy() diff --git a/value/pom.xml b/value/pom.xml index bc4be96ff..25b81d95b 100644 --- a/value/pom.xml +++ b/value/pom.xml @@ -1,5 +1,6 @@ - + immutables org.immutables