Repository navigation
feat(generator): add type modules and optional formatting - #318
Conversation
87608af to
6b6b0cc
Compare
Bergmann89
left a comment
There was a problem hiding this comment.
Hey @sundermann,
Thanks for this, I'd love to get this merged, but there is some rework needed before that:
Blocking
- Split output does not compile for dynamic types and substitution groups. E.g. for the
dynamic_typeandsubstitution_groupfeature schemas you getcannot find trait AnimalTypeTrait in this scopeinside the type modules.make_trait_implsproduces a bareFooTraitfor traits in the same namespace, andrender_trait_impls(steps/mod.rs:459-485) only rebases paths that start withsuper. - No test that pins the generated code. The tests only check
to_string().contains(...), which is why the issue above slipped through. Please add a feature test the usual way (generate_testwithexpected/*.rsreference files that get compiled viainclude!). One file per renderer with the type modules as inlinemod { ... }blocks is fine, no need for one file per module. Please cover at least a dynamic type / substitution group, the combination with namespace modules, and quick_xml with a read test.
Design / API
- Make it a generator flag:
GeneratorFlags::USE_TYPE_MODULES. That's in line withUSE_NAMESPACE_MODULESandUSE_SCHEMA_MODULES, which also define the module layout. The generator then already knows the type module when it builds paths (traits, references), so the generated paths are correct from the start and the token patching inrender_trait_implscan go away. It also keepsRendererFlags::all()unchanged: right now it silently switches everyone who uses it to the new layout (mixed_choice_with_anyhad to be changed for exactly that reason). - Rename
to_sourcetoto_code_with_formatto match the existingto_code. - New dependencies:
prettypleaseandsynwithfullare unconditional now. Please put them behind an optional feature (e.g.pretty), so build-script users who don't need formatting don't pay the compile time. syn::Errorin the public API makessyna public dependency. Please return the crate's own error type instead.
Documentation
- Please remove the README section. If you want to show how to use it, an example crate under
examples/is the better place.
Smaller things
module.rs: importErrorKindinstead of the inlinestd::io::ErrorKind::InvalidDatapath.
6b6b0cc to
dffab99
Compare
|
@Bergmann89 thanks for the review! Really appreciate it. Initially, I had stripped tests because I didn't want to make the PR huge. I've kept the current tests as is: Especially for large schematas this would be an substantial improvement. It fixes IDE / rust analyzer limitations for huge files. I also have a PoC that takes the generated split output and distributes it into multiple crates with a public facing crate that reexports the API to speed up compilation times (as mentioned in #232). |
dffab99 to
bffabe6
Compare
Bergmann89
left a comment
There was a problem hiding this comment.
Thanks for the update and the context! The type modules look really good now: the generator computes the paths, and the new feature tests cover exactly what I was hoping for. And I can see the use case for large schemas, so let's get this in.
I added the small things as suggestions. Apart from that, two things are still open:
- Unused imports in type modules. With
USE_TYPE_MODULES, some type modules get usings they don't need (e.g.ErrorKindandRawByteStrin simple and union types). You can see it when building the benchmark with the flag (20 warnings). The snapshot tests don't show it because the modules have#![allow(unused_imports)]. Please only add a using when the code that needs it is actually emitted. - Benchmark and examples:
benchmark/build.rsand thebpmn,read_writeandvsmeexamples useGeneratorFlags::all()and silently switch to type modules now. Please subtract the flag there like in the tests, so their output stays as it is.
Nit: please add Error::FormattingError at the end of the enum instead of the beginning.
And I'd be very interested in your PoC for #232 as well! Splitting the generated code into multiple crates sounds like a great next step on top of this. Feel free to open an issue or a draft PR for it once this one is in.
bffabe6 to
9bdcf74
Compare
Assign type modules before building references and inheritance trait paths. Add GeneratorFlags::USE_TYPE_MODULES and expose the owning module path in DataType. Preserve namespace re-exports, inline content, and private XML helpers while allocating collision-free file names. Add compiled reference fixtures for dynamic types and substitution groups, including namespace modules and quick-xml reads.
Add explicit Plain and Pretty output modes, with prettyplease and syn enabled only by the optional pretty feature. Keep the public enum variants available in both configurations and report a formatting error when Pretty is selected without that feature. Return crate-owned errors from both formatting entry points while preserving the existing IO-only writer API. Demonstrate separate files and explicit formatting in the type_modules example.
9bdcf74 to
9a1de5b
Compare
Adds selectable per-type output files and optional prettyplease formatting, so callers can generate readable bindings as smaller Rust files without custom splitting or formatting code.
Changes
GeneratorFlags::USE_TYPE_MODULESto assign each generated type its own module before building reference and inheritance trait paths. Public namespace and schema paths remain available through explicit re-exports.Module::export. Store each type's owning module inDataType::module_pathand exported items inModule::exports.unused_importsdenied. The split benchmark also builds with-Dunused-imports, without the original 20 warnings.bpmn,read_write, andvsmeexamples in their previous layout by subtractingUSE_TYPE_MODULESfrom theirGeneratorFlags::all()configurations.prettyCargo feature (prettypleaseandsyn/full).CodeFormat::Plainremains the default.CodeFormat::PrettyandError::FormattingErrorare available with or without the feature; selecting Pretty without it returns a formatting error. Both new formatting entry points return the crate'sError, including IO errors. The existingwrite_to_fileskeeps itsio::ErrorAPI.master.examples/type_modulescrate to demonstrate separate files and explicit formatting. Leave the README and release changelog unchanged.Breaking changes
GeneratorFlags::all()now includesUSE_TYPE_MODULES, changing the generated layout for callers usingall(). Subtract that flag to retain the previous layout. Ordinary generation remains unchanged unless the flag is enabled.DataTypeandModulestruct initializers must supply the newmodule_pathandexportsfields, respectively. Custom render steps should callModule::exportfor additional public items that need re-exporting from the namespace/schema module.quick_xml_serializeandquick_xml_deserializehelper modules are private. Use the serialization/deserialization traits' associated types instead of public helper paths. The unsplit layout keeps its existing helper visibility.Errorgains the unconditionalFormattingErrorvariant at the end of the enum, so exhaustive downstream matches must account for it.Checklist
update-expectationsand reviewedcargo fmt,cargo clippyandcargo testpass (see CONTRIBUTING.md)