Skip to content

Commit

Permalink
#638 default and derived encoding, virtual and derived fields
Browse files Browse the repository at this point in the history
should be a lot better now
  • Loading branch information
elucash committed Jan 3, 2018
1 parent b1f1f51 commit 69335f8
Show file tree
Hide file tree
Showing 17 changed files with 380 additions and 130 deletions.
4 changes: 4 additions & 0 deletions encode/src/org/immutables/encode/EncodingMetadata.java
Expand Up @@ -50,6 +50,10 @@


String[] thrown(); String[] thrown();


String[] annotations() default {};

String[] doc() default {};

String code(); String code();
} }
} }
27 changes: 27 additions & 0 deletions generator/src/org/immutables/generator/Builtins.java
Expand Up @@ -21,6 +21,7 @@
import com.google.common.base.Functions; import com.google.common.base.Functions;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;


Expand Down Expand Up @@ -178,6 +179,32 @@ public String toString() {
} }
}; };


public final Templates.Binary<Object, Collection<?>, Boolean> in =
new Templates.Binary<Object, Collection<?>, Boolean>() {
@Override
public Boolean apply(Object left, Collection<?> right) {
return right.contains(left);
}

@Override
public String toString() {
return Builtins.class.getSimpleName() + ".in";
}
};

public final Templates.Binary<Object, Collection<?>, Boolean> notin =
new Templates.Binary<Object, Collection<?>, Boolean>() {
@Override
public Boolean apply(Object left, Collection<?> right) {
return !right.contains(left);
}

@Override
public String toString() {
return Builtins.class.getSimpleName() + ".right";
}
};

public final Literal literal = new Literal(); public final Literal literal = new Literal();


public static final class Literal implements Function<Object, String> { public static final class Literal implements Function<Object, String> {
Expand Down
@@ -0,0 +1,24 @@
package org.immutables.fixture.encoding.defs;

import java.util.Date;
import org.immutables.encode.Encoding;

@Encoding
public class CompactDate {
@Encoding.Impl
private long time;

@Encoding.Expose
Date get() {
return toDate(time);
}

@Encoding.Of
static long fromDate(Date date) {
return date == null ? 0L : date.getTime();
}

private static Date toDate(long time) {
return time == 0L ? null : new Date(time);
}
}
Expand Up @@ -15,19 +15,24 @@
*/ */
package org.immutables.fixture.encoding; package org.immutables.fixture.encoding;


import java.util.Date;
import java.util.OptionalDouble; import java.util.OptionalDouble;
import java.util.OptionalInt; import java.util.OptionalInt;
import org.immutables.fixture.encoding.defs.CompactDateEnabled;
import org.immutables.fixture.encoding.defs.CompactOptionalDoubleEnabled; import org.immutables.fixture.encoding.defs.CompactOptionalDoubleEnabled;
import org.immutables.fixture.encoding.defs.CompactOptionalIntEnabled; import org.immutables.fixture.encoding.defs.CompactOptionalIntEnabled;
import org.immutables.fixture.encoding.defs.VoidEncodingEnabled; import org.immutables.fixture.encoding.defs.VoidEncodingEnabled;
import org.immutables.value.Value; import org.immutables.value.Value;


@CompactOptionalIntEnabled @CompactOptionalIntEnabled
@CompactOptionalDoubleEnabled @CompactOptionalDoubleEnabled
@CompactDateEnabled
@Value.Immutable @Value.Immutable
public abstract class DefaultDerivedEncs { public abstract class EncodingWithDefaultDerived {
abstract OptionalInt a(); abstract OptionalInt a();


abstract Date dt();

public @Value.Default OptionalInt i() { public @Value.Default OptionalInt i() {
return OptionalInt.empty(); return OptionalInt.empty();
} }
Expand All @@ -43,6 +48,10 @@ public abstract class DefaultDerivedEncs {
public @Value.Derived Void dv() { public @Value.Derived Void dv() {
return null; return null;
} }

public @Value.Derived Date ddt() {
return null;
}
} }


@CompactOptionalDoubleEnabled @CompactOptionalDoubleEnabled
Expand Down
@@ -0,0 +1,25 @@
package org.immutables.fixture.encoding;

import java.util.Date;
import org.immutables.fixture.encoding.defs.CompactDateEnabled;
import org.immutables.value.Value;

@CompactDateEnabled
public abstract class UseCompactLocalDateTime {
public abstract static class Base {
@Value.Default
public Date firstSeen() {
return new Date();
}

@Value.Default
public Date lastSeen() {
return firstSeen();
}
}

@Value.Immutable
public abstract static class SomeSubclass extends Base {
public abstract String name();
}
}
@@ -1,6 +1,7 @@
package org.immutables.value.processor; package org.immutables.value.processor;


import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import org.immutables.generator.AbstractTemplate; import org.immutables.generator.AbstractTemplate;
import org.immutables.generator.Generator; import org.immutables.generator.Generator;
import org.immutables.generator.Templates; import org.immutables.generator.Templates;
Expand Down Expand Up @@ -33,6 +34,8 @@ public abstract class AbstractValuesTemplate extends AbstractTemplate {
@Generator.Typedef @Generator.Typedef
protected DeclaringPackage Package; protected DeclaringPackage Package;


protected final ImmutableList<ValueAttribute> noAttributes = ImmutableList.of();

protected final String guava = UnshadeGuava.prefix(); protected final String guava = UnshadeGuava.prefix();


protected final LongBits longsFor = new LongBits(); protected final LongBits longsFor = new LongBits();
Expand Down
Expand Up @@ -2252,15 +2252,11 @@ this.[n] = null;
[for v in attributes if not (v.generateDefault or v.generateDerived), n = v.name] [for v in attributes if not (v.generateDefault or v.generateDerived), n = v.name]
[if v.hasVirtualImpl][rr.virtualImpl v][else]this.[n][/if] = [emptyImmutableInstance v '']; [if v.hasVirtualImpl][rr.virtualImpl v][else]this.[n][/if] = [emptyImmutableInstance v ''];
[/for] [/for]
[for v in attributes if v.generateDefault or v.generateDerived, n = v.name] [for v in attributes if v.generateDefault, n = v.name]
[if type.annotationType] [if type.annotationType]
this.[n] = DEFAULT_VALUE_[toConstant v.name]; this.[n] = DEFAULT_VALUE_[toConstant n];
[else] [else if not type.generateSafeDerived]
[if type.generateSafeDerived]
[if v.hasVirtualImpl][rr.virtualImpl v][else]this.[n][/if] = [disambiguateField type 'initShim'].[v.names.get]();
[else]
this.[n] = [valueFromValue v][invokeSuper v].[v.names.get]()[/valueFromValue]; this.[n] = [valueFromValue v][invokeSuper v].[v.names.get]()[/valueFromValue];
[/if]
[/if] [/if]
[/for] [/for]
[/template] [/template]
Expand Down Expand Up @@ -2289,13 +2285,14 @@ this.[n] = [valueFromValue v][invokeSuper v].[v.names.get]()[/valueFromValue];


private [type.typeImmutable.simple]() {[output.collapsible] private [type.typeImmutable.simple]() {[output.collapsible]
[generateConstructorDefaultAttributes type type.implementedAttributes] [generateConstructorDefaultAttributes type type.implementedAttributes]
[generateAfterConstruction type false false false] [generateDerivedConstruction type noAttributes]
[generateAfterConstruction type false]
[/output.collapsible]} [/output.collapsible]}
[else if type.generatePrivateNoargConstructor] [else if type.generatePrivateNoargConstructor]


private [type.typeImmutable.simple]() {[output.collapsible] private [type.typeImmutable.simple]() {[output.collapsible]
[generateConstructorNoAttributes type type.implementedAttributes] [generateConstructorNoAttributes type type.implementedAttributes]
[generateAfterConstruction type false true true] [generateAfterConstruction type false]
[/output.collapsible]} [/output.collapsible]}
[/if] [/if]
[if type.useConstructor andnot type.generateConstructorUseCopyConstructor] [if type.useConstructor andnot type.generateConstructorUseCopyConstructor]
Expand All @@ -2318,20 +2315,25 @@ this.[n] = [valueFromValue v][invokeSuper v].[v.names.get]()[/valueFromValue];
private [type.typeImmutable.simple]([output.linesShortable][for v in type.constructorArguments][if not for.first],[/if] private [type.typeImmutable.simple]([output.linesShortable][for v in type.constructorArguments][if not for.first],[/if]
[v.atNullability][constructorAcceptType v] [v.name][/for][/output.linesShortable]) { [v.atNullability][constructorAcceptType v] [v.name][/for][/output.linesShortable]) {
[/if] [/if]
[if type.constructorOmited or (type.hasEncodingValueOrVirtualFields or (type.generateSafeDerived and type.hasDerivedAttributes))]
[let shim][disambiguateField type 'initShim'][/let]
[for v in type.constructorArguments, n = v.name] [for v in type.constructorArguments, n = v.name]
[if v.hasVirtualImpl] [if v.generateDefault and type.generateSafeDerived]
[shim].[v.names.init]([valueFromValue v n]);
[else if v.hasVirtualImpl]
[rr.virtualImpl v] = [valueFromValue v n]; [rr.virtualImpl v] = [valueFromValue v n];
[else] [else]
this.[n] = [valueFromValue v n]; this.[n] = [valueFromValue v n];
[/if] [/if]
[/for] [/for]
[if type.generateSafeDerived] [generateConstructorDefaultAttributes type type.constructorOmited]
[for v in type.constructorArguments if v.generateDefault] [else][-- Alternatively a lot simpler implementation]
[disambiguateField type 'initShim'].[v.names.init](this.[v.name]); [for v in type.constructorArguments, n = v.name]
this.[n] = [valueFromValue v n];
[/for] [/for]
[/if] [/if]
[generateConstructorDefaultAttributes type type.constructorOmited] [generateDerivedConstruction type type.constructorArguments]
[generateAfterConstruction type false false false] [generateAfterConstruction type false]
} }
[/if] [/if]
[if type.generateBuilderConstructor] [if type.generateBuilderConstructor]
Expand All @@ -2353,19 +2355,15 @@ this.[n] = [valueFromValue v][invokeSuper v].[v.names.get]()[/valueFromValue];
} }
[/for] [/for]
[/if] [/if]
[for v in getters, n = v.name] [for v in getters if v.generateDefault, n = v.name]
[if v.generateDefault] [if type.annotationType ornot type.generateSafeDerived]
[if type.generateSafeDerived]
[if v.hasVirtualImpl][rr.virtualImpl v][else]this.[n][/if] = [disambiguateField type 'initShim'].[v.names.get]();
[else]
this.[n] = [if v.requiresTrackIsSet]builder.[v.names.isSet]()[else]builder.[n] != null[/if] this.[n] = [if v.requiresTrackIsSet]builder.[v.names.isSet]()[else]builder.[n] != null[/if]
? [valueFromBuilderAlt v v.requiresTrackIsSet]builder.[/valueFromBuilderAlt] ? [valueFromBuilderAlt v v.requiresTrackIsSet]builder.[/valueFromBuilderAlt]
: [if type.annotationType]DEFAULT_VALUE_[toConstant v.name][else][valueFromSuper v][invokeSuper v].[v.names.get]()[/valueFromSuper][/if]; : [if type.annotationType]DEFAULT_VALUE_[toConstant v.name][else][valueFromSuper v][invokeSuper v].[v.names.get]()[/valueFromSuper][/if];
[/if] [/if]
[/if]
[/for] [/for]
[generateDerivedConstruction type] [generateDerivedConstruction type noAttributes]
[generateAfterConstruction type true false false] [generateAfterConstruction type true]
} }
[/if] [/if]
[if type.useCopyMethods] [if type.useCopyMethods]
Expand All @@ -2381,26 +2379,35 @@ this.[n] = [valueFromValue v][invokeSuper v].[v.names.get]()[/valueFromValue];
[ann] [ann]
[/for] [/for]
public [type.typeImmutable.simple]([output.linesShortable] public [type.typeImmutable.simple]([output.linesShortable]
[for v in getters if not v.generateDerived][if not for.first], [for v in setters][if not for.first],
[/if][v.constructorParameterAnnotations][v.atNullability][immutableImplementationType v] [v.name][/for][/output.linesShortable]) { [/if][v.constructorParameterAnnotations][v.atNullability][immutableImplementationType v] [v.name][/for][/output.linesShortable]) {
[else] [else]
private [type.typeImmutable.simple]([output.linesShortable] private [type.typeImmutable.simple]([output.linesShortable]
[if type.synthCopyConstructor][type.typeImmutable.simple] [disambiguateField type 'original'], [if type.synthCopyConstructor][type.typeImmutable.simple] [disambiguateField type 'original'],
[/if][for v in getters if not v.generateDerived][if not for.first], [/if][for v in setters][if not for.first],
[/if][v.atNullability][immutableImplementationType v] [v.name][/for][/output.linesShortable]) { [/if][v.atNullability][immutableImplementationType v] [v.name][/for][/output.linesShortable]) {
[/if] [/if]
[for v in getters if not v.generateDerived] [if type.hasEncodingValueOrVirtualFields or (type.generateSafeDerived and type.hasDerivedAttributes)]
[if not v.hasVirtualImpl] [let shim][disambiguateField type 'initShim'][/let]
this.[v.name] = [v.name]; [for v in setters, n = v.name]
[if v.generateDefault and type.generateSafeDerived]
[shim].[v.names.init]([n]);
[else if v.hasVirtualImpl]
[rr.virtualImpl v] = [n];
[else]
this.[n] = [n];
[/if] [/if]
[/for] [/for]
[if type.generateSafeDerived and type.hasDerivedAttributes] [generateDerivedConstruction type setters]
[for v in getters if v.generateDefault] [else][-- Alternatively a lot simpler implementation]
[disambiguateField type 'initShim'].[v.names.init]([v.name]); [for v in setters, n = v.name]
this.[n] = [n];
[/for] [/for]
[/if] [for v in getters if v.generateDerived, n = v.name]
[generateDerivedConstruction type] this.[n] = [valueFromValue v][invokeSuper v].[v.names.get]()[/valueFromValue];
[generateAfterConstruction type false true false] [/for]
[/if]
[generateAfterConstruction type false]
} }
[/if] [/if]
[if type.generateSafeDerived] [if type.generateSafeDerived]
Expand All @@ -2413,17 +2420,6 @@ this.[n] = [valueFromValue v][invokeSuper v].[v.names.get]()[/valueFromValue];
[/for] [/for]
[/template] [/template]


[template generateDerivedConstruction Type type]
[for v in type.implementedAttributes if v.generateDerived]
[if type.generateSafeDerived and v.encoding]
[let getShim][disambiguateField type 'initShim'].[v.names.get]()[/let]
[if v.hasVirtualImpl][rr.virtualImpl v][else]this.[v.name][/if] = [getShim];
[else]
this.[v.name] = [maybeNonNullValue v][invokeSuper v].[v.names.get]()[/maybeNonNullValue];
[/if]
[/for]
[/template]

[template generateSafeDerivedShim Type type] [template generateSafeDerivedShim Type type]
[for deriveds = v for v in type.implementedAttributes if v.generateDefault or v.generateDerived] [for deriveds = v for v in type.implementedAttributes if v.generateDefault or v.generateDerived]


Expand All @@ -2434,31 +2430,41 @@ private static final byte STAGE_INITIALIZED = 1;
[hiddenMutableState type] [hiddenMutableState type]
private transient volatile InitShim [disambiguateField type 'initShim'] = new InitShim(); private transient volatile InitShim [disambiguateField type 'initShim'] = new InitShim();


[-- dancing around errorprone --]
[for f in deriveds if f.encoding]
[if for.first][if type allowsClasspathAnnotation 'com.google.errorprone.annotations.CanIgnoreReturnValue']
@com.google.errorprone.annotations.CanIgnoreReturnValue
[/if][/if]
[/for]
private final class InitShim { private final class InitShim {
[for v in deriveds] [for v in deriveds]
[let stage][disambiguateField type][v.name]BuildStage[/disambiguateField][/let] [let stage][disambiguateField type][v.name]BuildStage[/disambiguateField][/let]
[let invokeSuperGet][disambiguateAccessor type][v.names.get]Initialize[/disambiguateAccessor][/let] [let invokeSuperGet][disambiguateAccessor type][v.names.get]Initialize[/disambiguateAccessor][/let]
private byte [stage] = STAGE_UNINITIALIZED;
private [immutableImplementationType v] [v.name]; private [immutableImplementationType v] [v.name];
private byte [stage]; [if v.encoding][rr.shimFields v][/if]


[immutableImplementationType v] [v.names.get]() { [immutableImplementationType v] [v.names.get]() {
if ([stage] == STAGE_INITIALIZING) throw new [type.throwForInvalidImmutableState](formatInitCycleMessage()); if ([stage] == STAGE_INITIALIZING) throw new [type.throwForInvalidImmutableState](formatInitCycleMessage());
if ([stage] == STAGE_UNINITIALIZED) { if ([stage] == STAGE_UNINITIALIZED) {
[stage] = STAGE_INITIALIZING; [stage] = STAGE_INITIALIZING;
this.[v.name] = [valueFromSuper v][if v.defaultInterface][invokeSuperGet][else][invokeSuperQualified v].[v.names.get][/if]()[/valueFromSuper]; this.[v.name] = [valueFromSuper v][if v.defaultInterface][invokeSuperGet][else][invokeSuperQualified v].[v.names.get][/if]()[/valueFromSuper];
[if v.encoding][rr.shimAssign v][/if]
[stage] = STAGE_INITIALIZED; [stage] = STAGE_INITIALIZED;
} }
return this.[v.name]; return this.[v.name];
} }
[if v.encoding][rr.shimAccessor v][/if]
[if v.generateDefault] [if v.generateDefault]


void [v.names.init]([immutableImplementationType v] [v.name]) { void [v.names.init]([immutableImplementationType v] [v.name]) {
this.[v.name] = [v.name]; this.[v.name] = [v.name];
[if v.encoding][rr.shimAssign v][/if]
[stage] = STAGE_INITIALIZED; [stage] = STAGE_INITIALIZED;
} }
[/if] [/if]
[/for]


[/for]
private String formatInitCycleMessage() { private String formatInitCycleMessage() {
java.util.List<String> attributes = [if type.generateJdkOnly]new java.util.ArrayList[asDiamond 'String']()[else][guava].collect.Lists.newArrayList()[/if]; java.util.List<String> attributes = [if type.generateJdkOnly]new java.util.ArrayList[asDiamond 'String']()[else][guava].collect.Lists.newArrayList()[/if];
[for v in deriveds] [for v in deriveds]
Expand Down Expand Up @@ -2957,10 +2963,31 @@ public String toString() {
[/if] [/if]
[/template] [/template]


[template generateAfterConstruction Type type Boolean usingBuilder Boolean pureCopy Boolean skipEncoding] [template generateDerivedConstruction Type type Attribute... constructorArgs]
[if not skipEncoding] [-- first come things that have to be initialized before any of initShim kicks in]
[rr.assignDefaultFields type.implementedAttributes pureCopy] [for a in type.implementedAttributes]
[if a.generateDefault or a.generateDerived]
[if a.generateDerived andnot type.generateSafeDerived]
this.[a.name] = [valueFromValue a][invokeSuper a].[a.names.get]()[/valueFromValue];
[/if]
[else if a.encoding][-- non derived encodings]
[rr.derivedAssign a]
[/if]
[/for]
[-- now completing with initShim]
[if type.generateSafeDerived]
[let shim][disambiguateField type 'initShim'][/let]
[for a in type.implementedAttributes if a.generateDefault or a.generateDerived]
[if a.encoding]
[rr.shimAssignExtract a shim]
[else if a notin constructorArgs]
this.[a.name] = [shim].[a.names.get]();
[/if] [/if]
[/for]
[/if]
[/template]

[template generateAfterConstruction Type type Boolean usingBuilder]
[if type.usePrehashed] [if type.usePrehashed]
this.hashCode = [if type.hashCodeDefined]super.hashCode()[else][disambiguateAccessor type 'computeHashCode']()[/if]; this.hashCode = [if type.hashCodeDefined]super.hashCode()[else][disambiguateAccessor type 'computeHashCode']()[/if];
[/if] [/if]
Expand Down

0 comments on commit 69335f8

Please sign in to comment.