-
Notifications
You must be signed in to change notification settings - Fork 666
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
Add inline classes support for scalars #6352
Conversation
✅ Docs preview has no changesThe preview was not built because there were no changes. Build ID: d17423f264760e0c34caa9dd |
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.
Looks cool! I'm curious at the generated bytecode. Can you dump the adapters bytecode for a simple scalar/list primitive case ? Make sure there's no boxing?
interface JavaOperationsCodegenOptions : CommonCodegenOpt, OperationsCodegenOpt, JavaCodegenOpt | ||
interface KotlinOperationsCodegenOptions : CommonCodegenOpt, OperationsCodegenOpt, KotlinCodegenOpt | ||
interface JavaSchemaCodegenOptions : CommonCodegenOpt, SchemaCodegenOpt, JavaCodegenOpt | ||
interface KotlinSchemaCodegenOptions : CommonCodegenOpt, SchemaCodegenOpt, KotlinCodegenOpt |
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.
...o-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/KotlinCodegen.kt
Outdated
Show resolved
Hide resolved
internal val kotlinLabsDefinitions_0_5 = kotlinLabsDefinitions_0_4 + """ | ||
""${'"'} | ||
Possible values for the `coercion` argument of the `@inlineClass` directive. | ||
Since: 4.1.1 | ||
""${'"'} | ||
enum InlineClassCoercion { String, Boolean, Int, Long, Float, Double, Any } | ||
|
||
""${'"'} | ||
Generate an inline class for the given scalar type. The wrapped type is determined by the `coercion` argument. | ||
Since: 4.1.1 | ||
""${'"'} | ||
directive @inlineClass(coercion: InlineClassCoercion!) on SCALAR | ||
""" |
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.
Nice!
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.
Also reminder to add the matching definition on https://github.com/apollographql/specs if we agree on this
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.
...apollo-gradle-plugin-external/src/main/kotlin/com/apollographql/apollo/gradle/api/Service.kt
Outdated
Show resolved
Hide resolved
…ollo/compiler/codegen/kotlin/KotlinCodegen.kt Co-authored-by: Martin Bonnin <[email protected]>
Generated Kotlinpublic object InlineClassQuery_ResponseAdapter {
public object Data : Adapter<InlineClassQuery.Data> {
public val RESPONSE_NAMES: List<String> = listOf("nonNullableLength")
override fun fromJson(reader: JsonReader, customScalarAdapters: CustomScalarAdapters): InlineClassQuery.Data {
var _nonNullableLength: Length? = null
while (true) {
when (reader.selectName(RESPONSE_NAMES)) {
0 -> _nonNullableLength = custom.scalars.type.scalar.Length(com.apollographql.apollo.api.LongAdapter.fromJson(reader, customScalarAdapters))
else -> break
}
}
return InlineClassQuery.Data(
nonNullableLength = _nonNullableLength ?: missingField(reader, "nonNullableLength")
)
}
override fun toJson(
writer: JsonWriter,
customScalarAdapters: CustomScalarAdapters,
`value`: InlineClassQuery.Data,
) {
writer.name("nonNullableLength")
com.apollographql.apollo.api.LongAdapter.toJson(writer, customScalarAdapters, value.nonNullableLength.value)
}
}
} Decompiled Java equivalent @NotNull
public InlineClassQuery.Data fromJson(@NotNull JsonReader reader, @NotNull CustomScalarAdapters customScalarAdapters) {
Intrinsics.checkNotNullParameter(reader, "reader");
Intrinsics.checkNotNullParameter(customScalarAdapters, "customScalarAdapters");
Length _nonNullableLength = null;
while(true) {
int var4 = reader.selectName(RESPONSE_NAMES);
if (var4 != 0) {
InlineClassQuery.Data var10000 = new InlineClassQuery.Data;
if (_nonNullableLength != null) {
var10000.<init>(_nonNullableLength.unbox-impl(), (DefaultConstructorMarker)null);
return var10000;
} else {
Assertions.missingField(reader, "nonNullableLength");
throw new KotlinNothingValueException();
}
}
_nonNullableLength = Length.box-impl(Length.constructor-impl(((Number)Adapters.LongAdapter.fromJson(reader, customScalarAdapters)).longValue()));
}
}
public void toJson(@NotNull JsonWriter writer, @NotNull CustomScalarAdapters customScalarAdapters, @NotNull InlineClassQuery.Data value) {
Intrinsics.checkNotNullParameter(writer, "writer");
Intrinsics.checkNotNullParameter(customScalarAdapters, "customScalarAdapters");
Intrinsics.checkNotNullParameter(value, "value");
writer.name("nonNullableLength");
Adapters.LongAdapter.toJson(writer, customScalarAdapters, value.getNonNullableLength-7cMOgQw());
}
|
I guess we could do it by using a separate boolean. No idea if it's worth the added complexity without additional benchmarks though. |
Yeah thought of using booleans... honestly I'm not convinced it's worth it. I think this is still useful even with this un/boxing? |
Superseded by #6404 |
This adds 2 things:
Scalar mappings can indicate the target is an inline class, and the name of the wrapped property.
When doing so, the generated adapter calls the primitive adapter on the wrapped property to avoid boxing/unboxing.
To do this, new versions of
mapScalarToKotlinXyz()
are added that take the inline class target name and property name.Ability to generate inline classes for scalars.
Done by applying a new
@inlineClass
directive, e.g.extend scalar Length @inlineClass(coercion: Long)
This will generate:
When doing so, the mapping is also added (no need to call
mapScalarToXyz()
).Related to #6332.