-
Notifications
You must be signed in to change notification settings - Fork 758
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
Implement reflective support for Java Records #1381
Conversation
|
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.
Where do you actually pack the MR jar? I don't see any references to META-INF/versions/16/
Constructor<Object> constructor; | ||
try { | ||
//noinspection unchecked | ||
constructor = (Constructor<Object>) rawType.getDeclaredConstructor(constructorParams); |
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.
Is there no way to get a MethodHandle from the Class once we know it's a record? Can't believe they expect you to use ancient java.lang.reflect reflection to programmatically instantiate these...
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.
Honestly never used that API, let me look
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.
Good news is we can use MethodHandle for this but bad news is RecordComponent
itself still returns only Method
for its accessors :/
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.
moshi/src/main/java16/com/squareup/moshi/RecordJsonAdapter.java
Outdated
Show resolved
Hide resolved
moshi/src/main/java16/com/squareup/moshi/RecordJsonAdapter.java
Outdated
Show resolved
Hide resolved
moshi/src/main/java16/com/squareup/moshi/RecordJsonAdapter.java
Outdated
Show resolved
Hide resolved
moshi/src/main/java16/com/squareup/moshi/RecordJsonAdapter.java
Outdated
Show resolved
Hide resolved
Yup removed! I misunderstood the requirements for this. This basically just packages it like a simple jar and gates java 16 code on the Util check |
No MR jar probably means tools like Graal and D8 (and others) will choke processing the jar. Instead of a gated use and stub you can make the stub return null from a factory method and make the 16 class return a real implementation. Then you unconditionally call the factory and gate behavior on non-null values. |
ah good idea. Thanks for bearing with me, learning something new with these MR jars! |
This reverts commit 3eb768f.
We can just enable this everywhere now since we require JDK 16 anyway
Being reminded how much the java module system sucks when you have to configure stuff |
Gotta be public
Not a regression test in this case
- 13 | ||
- 14 | ||
- 15 | ||
- 16 |
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.
Not testing on Java 8 is annoying. Something to look into separately from this change.
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.
We can make the main tests run with java 8 via Gradle toolchains
dependencies { | ||
"compileOnly"(Dependencies.AnimalSniffer.annotations) | ||
"signature"(Dependencies.AnimalSniffer.java7Signature) | ||
if (project.name != "records-tests") { |
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.
Very nice
@@ -15,9 +15,36 @@ | |||
# | |||
|
|||
# For Dokka https://github.com/Kotlin/dokka/issues/1405 | |||
org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m | |||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 \ | |||
--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \ |
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.
These are ... unfortunate. The Dokka issue above seems unrelated. I think this is the tracking issue.
https://youtrack.jetbrains.com/issue/KT-45545
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.
The kapt parts are no longer relevant or on master
now at least with Kotlin 1.6
sourceCompatibility = JavaVersion.VERSION_1_8 | ||
targetCompatibility = JavaVersion.VERSION_1_8 | ||
tasks.withType<Test>().configureEach { | ||
// For kapt to work with kotlin-compile-testing |
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.
Tracking here: https://youtrack.jetbrains.com/issue/KT-45545
} | ||
|
||
val mainSourceSet by sourceSets.named("main") | ||
val java16 by sourceSets.creating { |
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.
neat
@@ -35,6 +70,8 @@ tasks.withType<KotlinCompile>() | |||
} | |||
|
|||
dependencies { | |||
// So the j16 source set can "see" main Moshi sources | |||
"java16Implementation"(mainSourceSet.output) |
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.
off topic: this syntax offends me so much
} | ||
|
||
@Test | ||
public void qualifiedValues() throws IOException { |
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.
awesome
import javax.annotation.Nullable; | ||
|
||
/** | ||
* This is just a simple shim for linking in {@link StandardJsonAdapters} and swapped with a real |
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 really like how this plugs in
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.
Feels very reminiscent of expect/actual
Map<String, Type> mappedTypeArgs = null; | ||
if (type instanceof ParameterizedType parameterizedType) { | ||
Type[] typeArgs = parameterizedType.getActualTypeArguments(); | ||
var typeVars = rawType.getTypeParameters(); |
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.
var! (My first time seeing this in real life)
} | ||
|
||
Map<String, Type> mappedTypeArgs = null; | ||
if (type instanceof ParameterizedType parameterizedType) { |
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 reads to me as very similar to Util.resolve()
. Presumably we can’t use that here because this needs more records stuff? Either way this behavior really wants to be extracted into a separately-testable thing
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.
return new RecordJsonAdapter<>(constructor, rawType.getSimpleName(), bindings).nullSafe(); | ||
}; | ||
|
||
private static record ComponentBinding<T>( |
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.
yo dog
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.
yeah I think the static is implicit but the IDE didn't give me a warning about it being redundant
private final String targetClass; | ||
private final MethodHandle constructor; | ||
private final ComponentBinding<Object>[] componentBindingsArray; | ||
private final JsonReader.Options options; |
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.
Yay options
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 think I’d like to do a follow-up to this to test its internal components, though that shouldn’t block release.
Porting from https://github.com/ZacSweers/MoshiX/tree/main/moshi-records-reflect
This makes a few changes along the way to make the build all happy with how we're doing this:
main
source set for linking inBUILT_IN_FACTORIES
, but this is booted out by the real one during packaging.-release 8
, which functionally accomplishes the samerecords-test
subproject, making it easier to both write new ones and also ensure our packaging rules for the jar is working correctly (we've had success with this in the past with the codegen artifact's shading being tested in a dedicated tests project)Resolves #1278
Tests are a little skimpy right now, happy to take suggestions on more we should add! Can also look at fleshing them out more in a followup PR