-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] Non-boxing 'addAll' Methods for Primitive Types #2389
base: develop
Are you sure you want to change the base?
Conversation
@@ -218,6 +218,13 @@ public Builder primitiveItems(@Nonnull Iterable<Integer> primitiveItems) { | |||
return this; | |||
} | |||
|
|||
public Builder addAllPrimitiveItems(@Nonnull int... primitiveItems) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically... if my words in the PR description are to be believed and I am mirroring Immutables, then this method should be generated with a name primitiveItems
. Very easy change to make if people find that clearer.
@@ -56,6 +56,14 @@ public boolean addAll(int index, Collection<? extends SafeLong> collection) { | |||
return delegate.addAllAtIndex(index, target); | |||
} | |||
|
|||
public void addAll(long... source) { | |||
for (long value : source) { | |||
// Doesn't use SafeLong creation because this causes unnecessary boxing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is a little too specific and doesn't explain how the underlying type holds longs and those must adhere to the abstraction.
*/ | ||
// This method modifies a list that can't handle nulls. Do not use this unless the nonNullCollections flag is set | ||
public static void addAllToDoubleList(Collection<Double> addTo, double[] elementsToAdd) { | ||
if (addTo instanceof ConjureDoubleList) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An inelegant solution to preserve the feedback on #2307 (comment), but still capture the optimization we added. Also has some prior art in addAll
.
@@ -40,7 +40,7 @@ public long longValue() { | |||
return longValue; | |||
} | |||
|
|||
private static long check(long value) { | |||
public static long check(long value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I increased the visibility on this, because the logic is simple enough that to satisfy it is tantamount to copying the implementation detail (which felt bad). But also the logic is so simple that we aren't overly exposing some internals. Besides having more places rely on this is likely to prevent skew between implementations (IMO).
LIST("List", false), | ||
DOUBLE_LIST("DoubleList", true), | ||
INTEGER_LIST("IntegerList", true), | ||
BOOLEAN_LIST("BooleanList", true), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But also maybe not? #2390
@@ -66,7 +100,7 @@ public static MethodSpec.Builder createCollectionSetterBuilder( | |||
field.name)); | |||
} | |||
|
|||
public static MethodSpec.Builder createOptionalSetterBuilder( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can extract this into a separate PR, but I noticed that we were overly exposing these methods which in turn was overly exposing the EnrichedField
type.
df23c89
to
5590778
Compare
@@ -767,10 +787,19 @@ private List<MethodSpec> createAuxiliarySetters(EnrichedField enriched, boolean | |||
Type type = enriched.conjureDef().getType(); | |||
Optional<LogSafety> safety = safetyEvaluator.getUsageTimeSafety(enriched.conjureDef()); | |||
|
|||
ImmutableList.Builder<MethodSpec> builder = ImmutableList.builder(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made this a builder so I could optionally add another method and not have to duplicate logic to return lists directly.
5590778
to
b021276
Compare
Before this PR
This is an alternative variant of #2312 which attempts to fix the boxing overhead merely introduced by the shape of our API (primitive types on both sides of the abstraction). However, there was some objection to that approach due to some stylistic and API design disagreements. This alternative seeks to remedy some of those concerns by following some "prior art" from libraries we accept / use all the time - Immutables.
Immutables will generate a vararg
addAll
variant for aList
collection of some primitive boxed type. For example,List<Long>
will produce something like:After this PR
This change first punches a hole through from the underlying eclipse-collections types e.g.
DoubleList
which has routines likepublic boolean addAll(int... source)
which allow for direct, non-boxed, additions to the type.Then, taking Immutables as inspiration, I wired up our codegen to leverage this abstraction. This alternative design addresses the mutability concerns as this API clearly communicates how data will be owned moving forward (i.e. copied). This implementation also addresses the concerns of having a setter that resets the type may cause order of operations bugs in the field while populating the builder.
Of Note
Yes... I am aware that the
Iterable
variant is a setter in the builder e.g.:This feels like a design oversight (IMO) seeing as how
primitiveItems
is already initialized statically andnewNonNullIntegerList
simply performs a copy usingaddAll
. Removing it from the field will be considerable work, so this will need to be inconsistent for the time being. And also previous design deficiencies cannot justify future designs.Tangent
Sorry if this is getting off topic, but that
Iterable
variant seems destined to be used incorrectly. Imagine the following code:Either way, necessary or not, I do not love the invalid state that is further representable on this API by adding an additional similarly named setter.