The issue is due to JCasC export feature design : as we only want to export things that differ from default values, we create a fresh new `GradleInstallation$DescriptorImpl` instance and compare properties.
But gradle plugin did manage the transition from `Gradle.DescriptorImpl` to `ToolDescriptor` relying on an `@Inject` delegate, which I think is a nice, concise and clean way to handle this. When JCasC do create a new instance it doesn't inject dependencies and the delegate call results in a NPE.
I'm not sure the best way to handle this. I like the @Inject-based delegate approach, compared to other implementations which do a systematic lookup to legacy Descriptor. On the other hand the root issue maybe is that those approach don't migrate data, they just pretend they implement the new API but tried to avoid having to manage data migration. Maybe a correct way to handle this is for `Gradle.DescriptorImpl` (and other) to populate `GradleInstallation$DescriptorImpl#installations` when some legacy data get loaded, and fully follow the intended `ToolDescriptor` design to host `installations` property.