polyxml 0.19.2__tar.gz → 0.20.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {polyxml-0.19.2 → polyxml-0.20.1}/Cargo.lock +5 -5
- {polyxml-0.19.2 → polyxml-0.20.1}/Cargo.toml +1 -1
- {polyxml-0.19.2 → polyxml-0.20.1}/PKG-INFO +1 -1
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/cpp/mod.rs +31 -13
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/csharp/mod.rs +207 -21
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/go/mod.rs +19 -10
- polyxml-0.20.1/crates/polyxml-core/src/codegen/java/codec.rs +480 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/java/mod.rs +109 -36
- polyxml-0.20.1/crates/polyxml-core/src/codegen/java/models.rs +335 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/mod.rs +49 -2
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/python/mod.rs +94 -13
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/rust/mod.rs +24 -13
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/typescript/mod.rs +21 -12
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/schema_parser/mod.rs +776 -21
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_csharp_codegen.rs +108 -0
- polyxml-0.20.1/crates/polyxml-core/tests/test_issue51_audit.rs +581 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_java_codegen.rs +270 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/pyproject.toml +1 -1
- {polyxml-0.19.2 → polyxml-0.20.1}/README.md +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/Cargo.toml +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/README.md +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/benches/core_benchmarks.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/converters.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/error.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/ir/mod.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/ir/tarjan.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/json.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/lib.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/parser.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/schema.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/serializer.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/transcoder.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/src/value.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_conformance.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_core.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_cpp_codegen.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_go_codegen.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_json.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_python_codegen.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_rust_codecs.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_rust_codegen.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_schema_ir.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_security.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_transcoder.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-core/tests/test_ts_codegen.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-python/Cargo.toml +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-python/README.md +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-python/src/lib.rs +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-python/tests/test_conformance.py +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-python/tests/test_generated_models.py +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-python/tests/test_json.py +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/crates/polyxml-python/tests/test_polyxml.py +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/python/polyxml/AGENT_GUIDE.md +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/python/polyxml/__init__.py +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/python/polyxml/compat/__init__.py +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/python/polyxml/compat/xsdata.py +0 -0
- {polyxml-0.19.2 → polyxml-0.20.1}/python/polyxml/py.typed +0 -0
|
@@ -549,7 +549,7 @@ dependencies = [
|
|
|
549
549
|
|
|
550
550
|
[[package]]
|
|
551
551
|
name = "polyxml"
|
|
552
|
-
version = "0.
|
|
552
|
+
version = "0.20.1"
|
|
553
553
|
dependencies = [
|
|
554
554
|
"criterion",
|
|
555
555
|
"heck",
|
|
@@ -567,14 +567,14 @@ dependencies = [
|
|
|
567
567
|
|
|
568
568
|
[[package]]
|
|
569
569
|
name = "polyxml-c"
|
|
570
|
-
version = "0.
|
|
570
|
+
version = "0.20.1"
|
|
571
571
|
dependencies = [
|
|
572
572
|
"polyxml",
|
|
573
573
|
]
|
|
574
574
|
|
|
575
575
|
[[package]]
|
|
576
576
|
name = "polyxml-cli"
|
|
577
|
-
version = "0.
|
|
577
|
+
version = "0.20.1"
|
|
578
578
|
dependencies = [
|
|
579
579
|
"clap",
|
|
580
580
|
"glob",
|
|
@@ -588,7 +588,7 @@ dependencies = [
|
|
|
588
588
|
|
|
589
589
|
[[package]]
|
|
590
590
|
name = "polyxml-js"
|
|
591
|
-
version = "0.
|
|
591
|
+
version = "0.20.1"
|
|
592
592
|
dependencies = [
|
|
593
593
|
"napi",
|
|
594
594
|
"napi-build",
|
|
@@ -598,7 +598,7 @@ dependencies = [
|
|
|
598
598
|
|
|
599
599
|
[[package]]
|
|
600
600
|
name = "polyxml-python"
|
|
601
|
-
version = "0.
|
|
601
|
+
version = "0.20.1"
|
|
602
602
|
dependencies = [
|
|
603
603
|
"lexical-core",
|
|
604
604
|
"polyxml",
|
|
@@ -4,7 +4,9 @@ use std::fmt::Write as FmtWrite;
|
|
|
4
4
|
use heck::{AsPascalCase, AsSnakeCase};
|
|
5
5
|
use serde::{Deserialize, Serialize};
|
|
6
6
|
|
|
7
|
-
use crate::codegen::{
|
|
7
|
+
use crate::codegen::{
|
|
8
|
+
build_type_name_map, lookup_type_name, sanitize_keyword, set_type_name_map, LanguageContext,
|
|
9
|
+
};
|
|
8
10
|
use crate::ir::{
|
|
9
11
|
EnumDef, PrimitiveType, QName, RestrictionFacets, SchemaIR, SimpleTypeDef, StructDef, TypeDef,
|
|
10
12
|
TypeRef, UnionDef,
|
|
@@ -157,7 +159,7 @@ impl LanguageContext for CppLanguageContext {
|
|
|
157
159
|
fn map_type_ref(&self, type_ref: &TypeRef) -> String {
|
|
158
160
|
match type_ref {
|
|
159
161
|
TypeRef::Primitive(prim) => self.map_primitive(*prim).to_string(),
|
|
160
|
-
TypeRef::Named(qname) =>
|
|
162
|
+
TypeRef::Named(qname) => type_ident(qname),
|
|
161
163
|
TypeRef::Boxed(inner) => format!("std::unique_ptr<{}>", self.map_type_ref(inner)),
|
|
162
164
|
TypeRef::List(inner) => format!("std::vector<{}>", self.map_type_ref(inner)),
|
|
163
165
|
}
|
|
@@ -239,6 +241,12 @@ pub struct CppCodegen {
|
|
|
239
241
|
context: CppLanguageContext,
|
|
240
242
|
}
|
|
241
243
|
|
|
244
|
+
/// Emitted C++ identifier for a named type, disambiguated across namespaces
|
|
245
|
+
/// for the IR currently being generated (issue #51 item 3).
|
|
246
|
+
fn type_ident(q: &QName) -> String {
|
|
247
|
+
lookup_type_name(q, || to_cpp_type_name(&q.local))
|
|
248
|
+
}
|
|
249
|
+
|
|
242
250
|
impl CppCodegen {
|
|
243
251
|
pub fn new(options: CppOptions) -> Self {
|
|
244
252
|
Self {
|
|
@@ -249,6 +257,7 @@ impl CppCodegen {
|
|
|
249
257
|
|
|
250
258
|
/// Generate complete header-only source (`.hpp`).
|
|
251
259
|
pub fn generate_header(&self, ir: &SchemaIR) -> String {
|
|
260
|
+
set_type_name_map(build_type_name_map(ir, to_cpp_type_name));
|
|
252
261
|
let mut out = String::new();
|
|
253
262
|
if let Some(ref header) = self.options.custom_header {
|
|
254
263
|
let trimmed = header.trim();
|
|
@@ -286,6 +295,7 @@ impl CppCodegen {
|
|
|
286
295
|
|
|
287
296
|
/// Generate complete C++20 module interface unit (`.cppm`).
|
|
288
297
|
pub fn generate_module_unit(&self, ir: &SchemaIR, module_name: &str) -> String {
|
|
298
|
+
set_type_name_map(build_type_name_map(ir, to_cpp_type_name));
|
|
289
299
|
let mut out = String::new();
|
|
290
300
|
if let Some(ref header) = self.options.custom_header {
|
|
291
301
|
let trimmed = header.trim();
|
|
@@ -470,7 +480,7 @@ endif()
|
|
|
470
480
|
// 1. Enums
|
|
471
481
|
for type_def in ir.types.values() {
|
|
472
482
|
if let TypeDef::Enum(enum_def) = type_def {
|
|
473
|
-
let enum_name =
|
|
483
|
+
let enum_name = type_ident(&enum_def.qname);
|
|
474
484
|
let full_type = format!("{}::{}", ns, enum_name);
|
|
475
485
|
writeln!(out, "template <>").unwrap();
|
|
476
486
|
writeln!(out, "struct glz::meta<{}> {{", full_type).unwrap();
|
|
@@ -498,7 +508,7 @@ endif()
|
|
|
498
508
|
let sorted_qnames = self.topological_sort_types(ir);
|
|
499
509
|
for qname in sorted_qnames {
|
|
500
510
|
if let Some(TypeDef::Struct(s)) = ir.types.get(&qname) {
|
|
501
|
-
let struct_name =
|
|
511
|
+
let struct_name = type_ident(&s.qname);
|
|
502
512
|
let full_type = format!("{}::{}", ns, struct_name);
|
|
503
513
|
writeln!(out, "template <>").unwrap();
|
|
504
514
|
writeln!(out, "struct glz::meta<{}> {{", full_type).unwrap();
|
|
@@ -570,7 +580,7 @@ concept XmlModel = requires(T a) {{
|
|
|
570
580
|
.values()
|
|
571
581
|
.filter_map(|t| {
|
|
572
582
|
if let TypeDef::Struct(s) = t {
|
|
573
|
-
Some(
|
|
583
|
+
Some(type_ident(&s.qname))
|
|
574
584
|
} else {
|
|
575
585
|
None
|
|
576
586
|
}
|
|
@@ -622,7 +632,7 @@ concept XmlModel = requires(T a) {{
|
|
|
622
632
|
writeln!(out, "/// {}", line).unwrap();
|
|
623
633
|
}
|
|
624
634
|
}
|
|
625
|
-
let type_name =
|
|
635
|
+
let type_name = type_ident(&simple.qname);
|
|
626
636
|
let base_type = self.context.map_type_ref(&simple.base_type);
|
|
627
637
|
writeln!(out, "using {} = {};\n", type_name, base_type).unwrap();
|
|
628
638
|
}
|
|
@@ -634,7 +644,7 @@ concept XmlModel = requires(T a) {{
|
|
|
634
644
|
}
|
|
635
645
|
}
|
|
636
646
|
|
|
637
|
-
let enum_name =
|
|
647
|
+
let enum_name = type_ident(&enum_def.qname);
|
|
638
648
|
writeln!(out, "enum class {} {{", enum_name).unwrap();
|
|
639
649
|
|
|
640
650
|
for variant in &enum_def.variants {
|
|
@@ -668,8 +678,16 @@ concept XmlModel = requires(T a) {{
|
|
|
668
678
|
writeln!(out, " return \"\";").unwrap();
|
|
669
679
|
writeln!(out, "}}\n").unwrap();
|
|
670
680
|
|
|
671
|
-
// from_string
|
|
672
|
-
|
|
681
|
+
// from_string — stem follows the disambiguated type name only when
|
|
682
|
+
// it differs from the natural one, preserving the historical
|
|
683
|
+
// snake-of-local form otherwise (issue #51 item 3).
|
|
684
|
+
let natural = to_cpp_type_name(&enum_def.qname.local);
|
|
685
|
+
let stem = if enum_name == natural {
|
|
686
|
+
AsSnakeCase(&enum_def.qname.local).to_string()
|
|
687
|
+
} else {
|
|
688
|
+
AsSnakeCase(&enum_name).to_string()
|
|
689
|
+
};
|
|
690
|
+
let func_name = format!("{stem}_from_string");
|
|
673
691
|
writeln!(
|
|
674
692
|
out,
|
|
675
693
|
"[[nodiscard]] inline std::optional<{}> {}(std::string_view s) noexcept {{",
|
|
@@ -697,7 +715,7 @@ concept XmlModel = requires(T a) {{
|
|
|
697
715
|
}
|
|
698
716
|
}
|
|
699
717
|
|
|
700
|
-
let union_name =
|
|
718
|
+
let union_name = type_ident(&u.qname);
|
|
701
719
|
|
|
702
720
|
// Check if branches have distinct types and no primitives
|
|
703
721
|
let mut branch_types = Vec::new();
|
|
@@ -758,17 +776,17 @@ concept XmlModel = requires(T a) {{
|
|
|
758
776
|
}
|
|
759
777
|
}
|
|
760
778
|
|
|
761
|
-
let struct_name =
|
|
779
|
+
let struct_name = type_ident(&s.qname);
|
|
762
780
|
let mut base_clause = String::new();
|
|
763
781
|
let mut simple_content_base: Option<String> = None;
|
|
764
782
|
|
|
765
783
|
if let Some(ref base_qname) = s.base_type {
|
|
766
784
|
if matches!(ir.types.get(base_qname), Some(TypeDef::Struct(_))) {
|
|
767
|
-
base_clause = format!(" : public {}",
|
|
785
|
+
base_clause = format!(" : public {}", type_ident(base_qname));
|
|
768
786
|
} else if let Some(prim) = PrimitiveType::from_xsd_name(&base_qname.local) {
|
|
769
787
|
simple_content_base = Some(self.context.map_primitive(prim).to_string());
|
|
770
788
|
} else if let Some(TypeDef::Simple(st)) = ir.types.get(base_qname) {
|
|
771
|
-
simple_content_base = Some(
|
|
789
|
+
simple_content_base = Some(type_ident(&st.qname));
|
|
772
790
|
}
|
|
773
791
|
}
|
|
774
792
|
|
|
@@ -8,9 +8,11 @@ use std::fmt::Write as FmtWrite;
|
|
|
8
8
|
use heck::{AsLowerCamelCase, AsPascalCase};
|
|
9
9
|
use serde::{Deserialize, Serialize};
|
|
10
10
|
|
|
11
|
-
use crate::codegen::{
|
|
11
|
+
use crate::codegen::{
|
|
12
|
+
build_type_name_map, lookup_type_name, sanitize_keyword, set_type_name_map, LanguageContext,
|
|
13
|
+
};
|
|
12
14
|
use crate::ir::{
|
|
13
|
-
EnumDef, FieldDef, FieldKind, PrimitiveType, RestrictionFacets, SchemaIR, SimpleTypeDef,
|
|
15
|
+
EnumDef, FieldDef, FieldKind, PrimitiveType, QName, RestrictionFacets, SchemaIR, SimpleTypeDef,
|
|
14
16
|
StructDef, TypeDef, TypeRef, UnionDef,
|
|
15
17
|
};
|
|
16
18
|
|
|
@@ -51,6 +53,9 @@ pub struct CSharpOptions {
|
|
|
51
53
|
pub emit_validation: bool,
|
|
52
54
|
/// Record emission kind (record class vs record struct)
|
|
53
55
|
pub record_kind: CSharpRecordKind,
|
|
56
|
+
/// Emit immutable records (default) instead of mutable classes.
|
|
57
|
+
#[serde(default = "default_use_records")]
|
|
58
|
+
pub use_records: bool,
|
|
54
59
|
/// Use modern C# 10+ file-scoped namespaces (`namespace Foo;`)
|
|
55
60
|
pub use_file_scoped_namespaces: bool,
|
|
56
61
|
/// Emit root element wrapper records or aliases
|
|
@@ -59,6 +64,10 @@ pub struct CSharpOptions {
|
|
|
59
64
|
pub custom_header: Option<String>,
|
|
60
65
|
}
|
|
61
66
|
|
|
67
|
+
fn default_use_records() -> bool {
|
|
68
|
+
true
|
|
69
|
+
}
|
|
70
|
+
|
|
62
71
|
impl Default for CSharpOptions {
|
|
63
72
|
fn default() -> Self {
|
|
64
73
|
Self {
|
|
@@ -69,6 +78,7 @@ impl Default for CSharpOptions {
|
|
|
69
78
|
source_gen_context_name: "PolyXmlJsonContext".to_string(),
|
|
70
79
|
emit_validation: true,
|
|
71
80
|
record_kind: CSharpRecordKind::Class,
|
|
81
|
+
use_records: true,
|
|
72
82
|
use_file_scoped_namespaces: true,
|
|
73
83
|
emit_root_records: true,
|
|
74
84
|
custom_header: None,
|
|
@@ -210,7 +220,7 @@ impl LanguageContext for CSharpLanguageContext {
|
|
|
210
220
|
fn map_type_ref(&self, type_ref: &TypeRef) -> String {
|
|
211
221
|
match type_ref {
|
|
212
222
|
TypeRef::Primitive(prim) => self.map_primitive(*prim).to_string(),
|
|
213
|
-
TypeRef::Named(qname) =>
|
|
223
|
+
TypeRef::Named(qname) => type_ident(qname),
|
|
214
224
|
TypeRef::Boxed(inner) => self.map_type_ref(inner),
|
|
215
225
|
TypeRef::List(inner) => format!("List<{}>", self.map_type_ref(inner)),
|
|
216
226
|
}
|
|
@@ -223,6 +233,12 @@ pub struct CSharpCodegen {
|
|
|
223
233
|
context: CSharpLanguageContext,
|
|
224
234
|
}
|
|
225
235
|
|
|
236
|
+
/// Emitted C# identifier for a named type, disambiguated across namespaces
|
|
237
|
+
/// for the IR currently being generated (issue #51 item 3).
|
|
238
|
+
fn type_ident(q: &QName) -> String {
|
|
239
|
+
lookup_type_name(q, || to_csharp_type_name(&q.local))
|
|
240
|
+
}
|
|
241
|
+
|
|
226
242
|
impl CSharpCodegen {
|
|
227
243
|
/// Creates a new C# code generator with the given configuration options.
|
|
228
244
|
pub fn new(options: CSharpOptions) -> Self {
|
|
@@ -234,6 +250,7 @@ impl CSharpCodegen {
|
|
|
234
250
|
|
|
235
251
|
/// Emits all types in the given SchemaIR as a single C# compilation unit.
|
|
236
252
|
pub fn generate_module(&self, ir: &SchemaIR) -> String {
|
|
253
|
+
set_type_name_map(build_type_name_map(ir, to_csharp_type_name));
|
|
237
254
|
let mut out = String::new();
|
|
238
255
|
|
|
239
256
|
if let Some(ref header) = self.options.custom_header {
|
|
@@ -342,7 +359,7 @@ impl CSharpCodegen {
|
|
|
342
359
|
// Enums
|
|
343
360
|
for def in ir.types.values() {
|
|
344
361
|
if let TypeDef::Enum(e) = def {
|
|
345
|
-
let name =
|
|
362
|
+
let name = type_ident(&e.qname);
|
|
346
363
|
writeln!(out, "{}[JsonSerializable(typeof({}))]", indent, name).unwrap();
|
|
347
364
|
}
|
|
348
365
|
}
|
|
@@ -350,7 +367,7 @@ impl CSharpCodegen {
|
|
|
350
367
|
// Simple types
|
|
351
368
|
for def in ir.types.values() {
|
|
352
369
|
if let TypeDef::Simple(s) = def {
|
|
353
|
-
let name =
|
|
370
|
+
let name = type_ident(&s.qname);
|
|
354
371
|
writeln!(out, "{}[JsonSerializable(typeof({}))]", indent, name).unwrap();
|
|
355
372
|
}
|
|
356
373
|
}
|
|
@@ -358,7 +375,7 @@ impl CSharpCodegen {
|
|
|
358
375
|
// Unions
|
|
359
376
|
for def in ir.types.values() {
|
|
360
377
|
if let TypeDef::Union(u) = def {
|
|
361
|
-
let name =
|
|
378
|
+
let name = type_ident(&u.qname);
|
|
362
379
|
writeln!(out, "{}[JsonSerializable(typeof({}))]", indent, name).unwrap();
|
|
363
380
|
}
|
|
364
381
|
}
|
|
@@ -366,12 +383,20 @@ impl CSharpCodegen {
|
|
|
366
383
|
// Structs
|
|
367
384
|
for def in ir.types.values() {
|
|
368
385
|
if let TypeDef::Struct(s) = def {
|
|
369
|
-
let name =
|
|
386
|
+
let name = type_ident(&s.qname);
|
|
370
387
|
writeln!(out, "{}[JsonSerializable(typeof({}))]", indent, name).unwrap();
|
|
371
388
|
writeln!(out, "{}[JsonSerializable(typeof(List<{}>))]", indent, name).unwrap();
|
|
372
389
|
}
|
|
373
390
|
}
|
|
374
391
|
|
|
392
|
+
if !self.options.use_records && self.options.emit_root_records {
|
|
393
|
+
for elem in ir.elements.values() {
|
|
394
|
+
let name = to_csharp_type_name(&elem.qname.local);
|
|
395
|
+
if name != self.context.map_type_ref(&elem.type_ref) {
|
|
396
|
+
writeln!(out, "{}[JsonSerializable(typeof({}))]", indent, name).unwrap();
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
375
400
|
let ctx_name = &self.options.source_gen_context_name;
|
|
376
401
|
writeln!(
|
|
377
402
|
out,
|
|
@@ -383,7 +408,7 @@ impl CSharpCodegen {
|
|
|
383
408
|
}
|
|
384
409
|
|
|
385
410
|
fn emit_enum(&self, out: &mut String, e: &EnumDef, indent: &str) {
|
|
386
|
-
let enum_name =
|
|
411
|
+
let enum_name = type_ident(&e.qname);
|
|
387
412
|
if let Some(ref doc) = e.documentation {
|
|
388
413
|
self.emit_docstring(out, doc, indent);
|
|
389
414
|
}
|
|
@@ -465,14 +490,51 @@ impl CSharpCodegen {
|
|
|
465
490
|
}
|
|
466
491
|
|
|
467
492
|
fn emit_simple(&self, out: &mut String, s: &SimpleTypeDef, indent: &str) {
|
|
468
|
-
if !s.facets.is_empty() {
|
|
469
|
-
let type_name =
|
|
493
|
+
if !s.facets.is_empty() || !self.options.use_records {
|
|
494
|
+
let type_name = type_ident(&s.qname);
|
|
470
495
|
let base_type = self.context.map_type_ref(&s.base_type);
|
|
471
496
|
|
|
472
497
|
if let Some(ref doc) = s.documentation {
|
|
473
498
|
self.emit_docstring(out, doc, indent);
|
|
474
499
|
}
|
|
475
500
|
|
|
501
|
+
if !self.options.use_records {
|
|
502
|
+
writeln!(
|
|
503
|
+
out,
|
|
504
|
+
"{}public class {}{}\n{}{{",
|
|
505
|
+
indent,
|
|
506
|
+
type_name,
|
|
507
|
+
if self.options.emit_validation {
|
|
508
|
+
" : IValidatableObject"
|
|
509
|
+
} else {
|
|
510
|
+
""
|
|
511
|
+
},
|
|
512
|
+
indent
|
|
513
|
+
)
|
|
514
|
+
.unwrap();
|
|
515
|
+
if self.options.emit_xml_attributes {
|
|
516
|
+
writeln!(out, "{} [XmlText]", indent).unwrap();
|
|
517
|
+
}
|
|
518
|
+
writeln!(
|
|
519
|
+
out,
|
|
520
|
+
"{} public {} Value {{ get; set; }} = default!;",
|
|
521
|
+
indent, base_type
|
|
522
|
+
)
|
|
523
|
+
.unwrap();
|
|
524
|
+
writeln!(
|
|
525
|
+
out,
|
|
526
|
+
"{} public {}() {{ }}\n{} public {}({} value) {{ Value = value; }}",
|
|
527
|
+
indent, type_name, indent, type_name, base_type
|
|
528
|
+
)
|
|
529
|
+
.unwrap();
|
|
530
|
+
if self.options.emit_validation {
|
|
531
|
+
writeln!(out, "{} public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)\n{} {{", indent, indent).unwrap();
|
|
532
|
+
self.emit_facet_checks(out, &s.facets, "Value", &format!("{} ", indent));
|
|
533
|
+
writeln!(out, "{} yield break;\n{} }}", indent, indent).unwrap();
|
|
534
|
+
}
|
|
535
|
+
writeln!(out, "{}}}\n", indent).unwrap();
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
476
538
|
writeln!(
|
|
477
539
|
out,
|
|
478
540
|
"{}public sealed record {}([property: XmlText] {} Value) : IValidatableObject",
|
|
@@ -504,7 +566,7 @@ impl CSharpCodegen {
|
|
|
504
566
|
}
|
|
505
567
|
|
|
506
568
|
fn emit_union(&self, out: &mut String, u: &UnionDef, indent: &str) {
|
|
507
|
-
let choice_name =
|
|
569
|
+
let choice_name = type_ident(&u.qname);
|
|
508
570
|
if let Some(ref doc) = u.documentation {
|
|
509
571
|
self.emit_docstring(out, doc, indent);
|
|
510
572
|
}
|
|
@@ -522,7 +584,31 @@ impl CSharpCodegen {
|
|
|
522
584
|
}
|
|
523
585
|
}
|
|
524
586
|
|
|
525
|
-
|
|
587
|
+
if !self.options.use_records && self.options.emit_json_attributes {
|
|
588
|
+
for branch in &u.branches {
|
|
589
|
+
writeln!(
|
|
590
|
+
out,
|
|
591
|
+
"{}[JsonDerivedType(typeof({}.{}), {:?})]",
|
|
592
|
+
indent,
|
|
593
|
+
choice_name,
|
|
594
|
+
to_csharp_type_name(&branch.variant_name),
|
|
595
|
+
branch.xml_name
|
|
596
|
+
)
|
|
597
|
+
.unwrap();
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
writeln!(
|
|
601
|
+
out,
|
|
602
|
+
"{}public abstract {} {}",
|
|
603
|
+
indent,
|
|
604
|
+
if self.options.use_records {
|
|
605
|
+
"record"
|
|
606
|
+
} else {
|
|
607
|
+
"class"
|
|
608
|
+
},
|
|
609
|
+
choice_name
|
|
610
|
+
)
|
|
611
|
+
.unwrap();
|
|
526
612
|
writeln!(out, "{}{{", indent).unwrap();
|
|
527
613
|
|
|
528
614
|
for branch in &u.branches {
|
|
@@ -546,6 +632,24 @@ impl CSharpCodegen {
|
|
|
546
632
|
format!("[property: {}] ", branch_attrs.join(", "))
|
|
547
633
|
};
|
|
548
634
|
|
|
635
|
+
if !self.options.use_records {
|
|
636
|
+
writeln!(
|
|
637
|
+
out,
|
|
638
|
+
"{} public sealed class {} : {}\n{} {{",
|
|
639
|
+
indent, variant_name, choice_name, indent
|
|
640
|
+
)
|
|
641
|
+
.unwrap();
|
|
642
|
+
writeln!(
|
|
643
|
+
out,
|
|
644
|
+
"{} {}public {} Value {{ get; set; }} = default!;",
|
|
645
|
+
indent,
|
|
646
|
+
xml_attr.replace("[property: ", "["),
|
|
647
|
+
branch_type
|
|
648
|
+
)
|
|
649
|
+
.unwrap();
|
|
650
|
+
writeln!(out, "{} public {}() {{ }}\n{} public {}({} value) {{ Value = value; }}\n{} }}", indent, variant_name, indent, variant_name, branch_type, indent).unwrap();
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
549
653
|
writeln!(
|
|
550
654
|
out,
|
|
551
655
|
"{} public sealed record {}({}{} Value) : {}",
|
|
@@ -567,7 +671,7 @@ impl CSharpCodegen {
|
|
|
567
671
|
}
|
|
568
672
|
|
|
569
673
|
fn emit_struct(&self, out: &mut String, s: &StructDef, ir: &SchemaIR, indent: &str) {
|
|
570
|
-
let struct_name =
|
|
674
|
+
let struct_name = type_ident(&s.qname);
|
|
571
675
|
if let Some(ref doc) = s.documentation {
|
|
572
676
|
self.emit_docstring(out, doc, indent);
|
|
573
677
|
}
|
|
@@ -595,7 +699,7 @@ impl CSharpCodegen {
|
|
|
595
699
|
let mut base_clause = Vec::new();
|
|
596
700
|
if let Some(ref base_qname) = s.base_type {
|
|
597
701
|
if matches!(ir.types.get(base_qname), Some(TypeDef::Struct(_))) {
|
|
598
|
-
let base_name =
|
|
702
|
+
let base_name = type_ident(base_qname);
|
|
599
703
|
base_clause.push(base_name);
|
|
600
704
|
}
|
|
601
705
|
}
|
|
@@ -609,6 +713,39 @@ impl CSharpCodegen {
|
|
|
609
713
|
format!(" : {}", base_clause.join(", "))
|
|
610
714
|
};
|
|
611
715
|
|
|
716
|
+
if !self.options.use_records {
|
|
717
|
+
writeln!(
|
|
718
|
+
out,
|
|
719
|
+
"{}public class {}{}\n{}{{",
|
|
720
|
+
indent, struct_name, implements_str, indent
|
|
721
|
+
)
|
|
722
|
+
.unwrap();
|
|
723
|
+
writeln!(out, "{} public {}() {{ }}", indent, struct_name).unwrap();
|
|
724
|
+
for f in &s.fields {
|
|
725
|
+
let name = to_csharp_property_name(&f.name, Some(&struct_name));
|
|
726
|
+
let ty = self.map_field_type(f, ir);
|
|
727
|
+
let attrs = self
|
|
728
|
+
.build_field_attributes(f, ir)
|
|
729
|
+
.replace("[property: ", "[");
|
|
730
|
+
let initial = if f.cardinality.is_list() || f.type_ref.is_list() {
|
|
731
|
+
"new()"
|
|
732
|
+
} else {
|
|
733
|
+
"default!"
|
|
734
|
+
};
|
|
735
|
+
writeln!(
|
|
736
|
+
out,
|
|
737
|
+
"{} {}public {} {} {{ get; set; }} = {};",
|
|
738
|
+
indent, attrs, ty, name, initial
|
|
739
|
+
)
|
|
740
|
+
.unwrap();
|
|
741
|
+
}
|
|
742
|
+
if self.options.emit_validation {
|
|
743
|
+
self.emit_struct_validator(out, s, indent);
|
|
744
|
+
}
|
|
745
|
+
writeln!(out, "{}}}\n", indent).unwrap();
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
|
|
612
749
|
// Collect fields and parameters
|
|
613
750
|
if s.fields.is_empty() {
|
|
614
751
|
writeln!(
|
|
@@ -688,8 +825,18 @@ impl CSharpCodegen {
|
|
|
688
825
|
}
|
|
689
826
|
|
|
690
827
|
fn emit_struct_validator(&self, out: &mut String, s: &StructDef, indent: &str) {
|
|
691
|
-
let struct_name =
|
|
692
|
-
let new_kw = if
|
|
828
|
+
let struct_name = type_ident(&s.qname);
|
|
829
|
+
let new_kw = if !self.options.use_records {
|
|
830
|
+
if s.base_type.is_some() {
|
|
831
|
+
"override "
|
|
832
|
+
} else {
|
|
833
|
+
"virtual "
|
|
834
|
+
}
|
|
835
|
+
} else if s.base_type.is_some() {
|
|
836
|
+
"new "
|
|
837
|
+
} else {
|
|
838
|
+
""
|
|
839
|
+
};
|
|
693
840
|
writeln!(
|
|
694
841
|
out,
|
|
695
842
|
"{} public {}IEnumerable<ValidationResult> Validate(ValidationContext validationContext)",
|
|
@@ -698,6 +845,9 @@ impl CSharpCodegen {
|
|
|
698
845
|
.unwrap();
|
|
699
846
|
writeln!(out, "{} {{", indent).unwrap();
|
|
700
847
|
|
|
848
|
+
if !self.options.use_records && s.base_type.is_some() {
|
|
849
|
+
writeln!(out, "{} foreach (var result in base.Validate(validationContext)) yield return result;", indent).unwrap();
|
|
850
|
+
}
|
|
701
851
|
let mut has_checks = false;
|
|
702
852
|
for f in &s.fields {
|
|
703
853
|
let prop_name = to_csharp_property_name(&f.name, Some(&struct_name));
|
|
@@ -799,9 +949,9 @@ impl CSharpCodegen {
|
|
|
799
949
|
TypeRef::Primitive(p) => self.context.map_primitive(*p).to_string(),
|
|
800
950
|
TypeRef::Named(qn) => {
|
|
801
951
|
if let Some(TypeDef::Union(u)) = ir.types.get(qn) {
|
|
802
|
-
|
|
952
|
+
type_ident(&u.qname)
|
|
803
953
|
} else {
|
|
804
|
-
|
|
954
|
+
type_ident(qn)
|
|
805
955
|
}
|
|
806
956
|
}
|
|
807
957
|
TypeRef::Boxed(inner) => self.context.map_type_ref(inner),
|
|
@@ -828,7 +978,7 @@ impl CSharpCodegen {
|
|
|
828
978
|
// If the field is a choice (UnionDef), emit XmlElement("branchXml", typeof(BranchType))
|
|
829
979
|
if let TypeRef::Named(ref qname) = f.type_ref {
|
|
830
980
|
if let Some(TypeDef::Union(u)) = ir.types.get(qname) {
|
|
831
|
-
let choice_name =
|
|
981
|
+
let choice_name = type_ident(&u.qname);
|
|
832
982
|
for branch in &u.branches {
|
|
833
983
|
let variant_name = to_csharp_type_name(&branch.variant_name);
|
|
834
984
|
parts.push(format!(
|
|
@@ -888,10 +1038,46 @@ impl CSharpCodegen {
|
|
|
888
1038
|
writeln!(out, "{}[XmlRoot(\"{}\")]", indent, elem.qname.local).unwrap();
|
|
889
1039
|
}
|
|
890
1040
|
}
|
|
1041
|
+
if !self.options.use_records {
|
|
1042
|
+
let can_extend = matches!(&elem.type_ref, TypeRef::Named(q) if matches!(ir.types.get(q), Some(TypeDef::Struct(_) | TypeDef::Simple(_))));
|
|
1043
|
+
if !can_extend {
|
|
1044
|
+
writeln!(
|
|
1045
|
+
out,
|
|
1046
|
+
"{}public sealed class {}\n{}{{",
|
|
1047
|
+
indent, elem_name, indent
|
|
1048
|
+
)
|
|
1049
|
+
.unwrap();
|
|
1050
|
+
if self.options.emit_xml_attributes {
|
|
1051
|
+
let attribute = if matches!(&elem.type_ref, TypeRef::Named(q)
|
|
1052
|
+
if matches!(ir.types.get(q), Some(TypeDef::Union(_))))
|
|
1053
|
+
{
|
|
1054
|
+
"XmlElement"
|
|
1055
|
+
} else {
|
|
1056
|
+
"XmlText"
|
|
1057
|
+
};
|
|
1058
|
+
writeln!(out, "{} [{}]", indent, attribute).unwrap();
|
|
1059
|
+
}
|
|
1060
|
+
writeln!(
|
|
1061
|
+
out,
|
|
1062
|
+
"{} public {} Value {{ get; set; }} = default!;\n{}}}\n",
|
|
1063
|
+
indent, target_type, indent
|
|
1064
|
+
)
|
|
1065
|
+
.unwrap();
|
|
1066
|
+
continue;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
891
1069
|
writeln!(
|
|
892
1070
|
out,
|
|
893
|
-
"{}public sealed
|
|
894
|
-
indent,
|
|
1071
|
+
"{}public sealed {} {} : {}\n{}{{",
|
|
1072
|
+
indent,
|
|
1073
|
+
if self.options.use_records {
|
|
1074
|
+
"record"
|
|
1075
|
+
} else {
|
|
1076
|
+
"class"
|
|
1077
|
+
},
|
|
1078
|
+
elem_name,
|
|
1079
|
+
target_type,
|
|
1080
|
+
indent
|
|
895
1081
|
)
|
|
896
1082
|
.unwrap();
|
|
897
1083
|
writeln!(out, "{} public {}() : base() {{ }}", indent, elem_name).unwrap();
|