Skip to content

Commit 7e20170

Browse files
committed
#1569 merge from static overloads mode
1 parent f8edd1f commit 7e20170

10 files changed

Lines changed: 111 additions & 6 deletions

File tree

value-annotations/src/org/immutables/value/Value.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,6 +1716,27 @@
17161716
*/
17171717
boolean builderToString() default false;
17181718

1719+
/**
1720+
* Builder has {@link #from()} method generated which initializes builder values from an instance.
1721+
* When abstract value type has some supertypes, an abstract class and or interfaces, from method can populate
1722+
* values, even partially from an instances of such supertypes. Some release ago, we've started
1723+
* to use runtime {@code instanceof} check when choosing which supertypes are implemented by a given instance
1724+
* and some, arguably, complicated machinery with bit masks to initialize attributes not more than once.
1725+
* This change was motivated by the style of working when once would want to initialize values fully
1726+
* from instances, regardless of "segregated" interfaces. In the cases where generics are used in supertype
1727+
* attributes, and when instances happen to implement same interfaces but with different type arguments,
1728+
* this dynamic approach can result in {@link ClassCastException} or heap pollution.
1729+
*
1730+
* <p>The other way is to just have copy logic in
1731+
* statically resolved, i.e. at compile time overload, and copy/initialize only those properties which
1732+
* are strictly defined by a supertype. When this {@code mergeFromSupertypesDynamically} style flag is
1733+
* set to {@code false}, the generated code will switch to using simpler copy logic in compile-time resolved
1734+
* overloads. The default is {@code true} to use {@code instanceof} checks and bit masks under the hood
1735+
* to extract all attributes using all implemented supertypes.
1736+
* @return {@code false} to disable. The default is {@code true}
1737+
*/
1738+
boolean mergeFromSupertypesDynamically() default true;
1739+
17191740
/**
17201741
* If implementation visibility is more restrictive than visibility of abstract value type, then
17211742
* implementation type will not be exposed as a return type of {@code build()} or {@code of()}

value-fixture/src/org/immutables/fixture/builder/huge/ChildOfHugeParents.java renamed to value-fixture/src/org/immutables/fixture/builder/from/ChildOfHugeParents.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package org.immutables.fixture.builder.huge;
1+
package org.immutables.fixture.builder.from;
22

33
import org.immutables.value.Value;
44

value-fixture/src/org/immutables/fixture/builder/huge/CompactTypes.java renamed to value-fixture/src/org/immutables/fixture/builder/from/CompactTypes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package org.immutables.fixture.builder.huge;
1+
package org.immutables.fixture.builder.from;
22

33
import org.immutables.value.Value;
44

value-fixture/src/org/immutables/fixture/builder/huge/HugeParentOne.java renamed to value-fixture/src/org/immutables/fixture/builder/from/HugeParentOne.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package org.immutables.fixture.builder.huge;
1+
package org.immutables.fixture.builder.from;
22

33
public interface HugeParentOne {
44
int getFirst();

value-fixture/src/org/immutables/fixture/builder/huge/HugeParentTwo.java renamed to value-fixture/src/org/immutables/fixture/builder/from/HugeParentTwo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package org.immutables.fixture.builder.huge;
1+
package org.immutables.fixture.builder.from;
22

33
public interface HugeParentTwo {
44
String getAlpha();
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package org.immutables.fixture.builder.from;
2+
3+
import java.util.List;
4+
import javax.annotation.Nullable;
5+
import org.immutables.value.Value;
6+
7+
@Value.Style(mergeFromSupertypesDynamically = false)
8+
@Value.Enclosing
9+
public interface StaticSuperTypes {
10+
interface StParentOne {
11+
int getFirst();
12+
13+
int getSecond();
14+
15+
int getThird();
16+
17+
int getFourth();
18+
19+
int getFifth();
20+
21+
int getSixth();
22+
23+
int getSeventh();
24+
25+
@Nullable String nully();
26+
}
27+
28+
interface StParentTwo<T> {
29+
String getAlpha();
30+
31+
String getBeta();
32+
33+
String getGamma();
34+
35+
String getDelta();
36+
37+
String getEpsilon();
38+
39+
String getZeta();
40+
41+
List<T> data();
42+
}
43+
44+
@Value.Immutable
45+
interface StChild extends StParentOne, StParentTwo<String> {
46+
int getFirst();
47+
48+
int getSecond();
49+
}
50+
}

value-processor/src/org/immutables/value/processor/Immutables.generator

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1755,8 +1755,12 @@ public interface [tb.nameBuildFinal][type.generics] {
17551755
[atCanIgnoreReturnValue type]
17561756
public final [builderReturnType type] [type.names.from]([type.typeImmutable.relative] instance) {
17571757
[requireNonNull type](instance, "instance");
1758+
[if type.dynamicBuildFromTypes]
17581759
mergeInternal(instance);
17591760
return [builderReturnThis type];
1761+
[else]
1762+
return [type.names.from](([type.typeAbstract.relative]) instance);
1763+
[/if]
17601764
}
17611765

17621766
/**
@@ -1767,7 +1771,13 @@ public interface [tb.nameBuildFinal][type.generics] {
17671771
[atCanIgnoreReturnValue type]
17681772
public final [builderReturnType type] [type.names.from]([type.typeAbstract.relative] instance) {
17691773
[requireNonNull type](instance, "instance");
1774+
[if type.dynamicBuildFromTypes]
17701775
mergeInternal(instance);
1776+
[else]
1777+
[for v in setters]
1778+
[buildFromAttribute v]
1779+
[/for]
1780+
[/if]
17711781
return [builderReturnThis type];
17721782
}
17731783
[else]
@@ -1780,13 +1790,24 @@ public interface [tb.nameBuildFinal][type.generics] {
17801790
[atCanIgnoreReturnValue type]
17811791
public final [builderReturnType type] [type.names.from]([s.type] instance) {
17821792
[requireNonNull type](instance, "instance");
1793+
[if type.dynamicBuildFromTypes]
17831794
mergeInternal(instance);
1795+
[else]
1796+
[for v in s.attributes]
1797+
[if v.nullableInSupertype]
1798+
[buildFromAttributeNullableSupertype v]
1799+
[else]
1800+
[buildFromAttribute v]
1801+
[/if]
1802+
[/for]
1803+
[/if]
17841804
return [builderReturnThis type];
17851805
}
17861806
[/if]
17871807
[/for]
1788-
1808+
[if type.dynamicBuildFromTypes]
17891809
[for bs = type.buildFromTypes]
1810+
17901811
[if bs.hasWildcards andnot type.suppressesUncheckedWarning]
17911812
@SuppressWarnings("unchecked")
17921813
[/if]
@@ -1882,6 +1903,7 @@ public interface [tb.nameBuildFinal][type.generics] {
18821903
[/for]
18831904
[/if]
18841905
[/for]
1906+
[/if][--dynamic--]
18851907
[else]
18861908

18871909
/**

value-processor/src/org/immutables/value/processor/meta/StyleInfo.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,11 @@ public Class<? extends Annotation> fallbackNullableAnnotation() {
480480
@Override
481481
public abstract boolean builderToString();
482482

483+
@Value.Parameter
484+
@Override
485+
public abstract boolean mergeFromSupertypesDynamically();
486+
487+
483488
static StyleInfo infoFrom(StyleMirror input) {
484489
return ImmutableStyleInfo.of(
485490
input.get(),
@@ -581,6 +586,7 @@ static StyleInfo infoFrom(StyleMirror input) {
581586
input.limitStringLengthInToString(),
582587
input.jakarta(),
583588
input.legacyAccessorOrdering(),
584-
input.builderToString());
589+
input.builderToString(),
590+
input.mergeFromSupertypesDynamically());
585591
}
586592
}

value-processor/src/org/immutables/value/processor/meta/ValueMirrors.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@ private ValueMirrors() {}
337337

338338
boolean builderToString() default false;
339339

340+
boolean mergeFromSupertypesDynamically() default true;
341+
340342
enum ImplementationVisibility {
341343
PUBLIC,
342344
SAME,

value-processor/src/org/immutables/value/processor/meta/ValueType.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,10 @@ public FromSupertypesModel getBuildFromTypes() {
14971497
return buildFromTypes;
14981498
}
14991499

1500+
public boolean isDynamicBuildFromTypes() {
1501+
return style().mergeFromSupertypesDynamically();
1502+
}
1503+
15001504
public Serialization serial = Serialization.NONE;
15011505

15021506
public ImmutableList<String> throwing = ImmutableList.of();

0 commit comments

Comments
 (0)