polyxml 0.20.0__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.20.0 → polyxml-0.20.1}/Cargo.lock +5 -5
- {polyxml-0.20.0 → polyxml-0.20.1}/Cargo.toml +1 -1
- {polyxml-0.20.0 → polyxml-0.20.1}/PKG-INFO +1 -1
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/cpp/mod.rs +31 -13
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/csharp/mod.rs +25 -16
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/go/mod.rs +19 -10
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/java/codec.rs +8 -12
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/java/mod.rs +18 -8
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/java/models.rs +2 -2
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/mod.rs +49 -2
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/python/mod.rs +94 -13
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/rust/mod.rs +24 -13
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/codegen/typescript/mod.rs +21 -12
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/schema_parser/mod.rs +776 -21
- polyxml-0.20.1/crates/polyxml-core/tests/test_issue51_audit.rs +581 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/pyproject.toml +1 -1
- {polyxml-0.20.0 → polyxml-0.20.1}/README.md +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/Cargo.toml +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/README.md +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/benches/core_benchmarks.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/converters.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/error.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/ir/mod.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/ir/tarjan.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/json.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/lib.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/parser.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/schema.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/serializer.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/transcoder.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/src/value.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_conformance.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_core.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_cpp_codegen.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_csharp_codegen.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_go_codegen.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_java_codegen.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_json.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_python_codegen.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_rust_codecs.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_rust_codegen.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_schema_ir.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_security.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_transcoder.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-core/tests/test_ts_codegen.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-python/Cargo.toml +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-python/README.md +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-python/src/lib.rs +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-python/tests/test_conformance.py +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-python/tests/test_generated_models.py +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-python/tests/test_json.py +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/crates/polyxml-python/tests/test_polyxml.py +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/python/polyxml/AGENT_GUIDE.md +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/python/polyxml/__init__.py +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/python/polyxml/compat/__init__.py +0 -0
- {polyxml-0.20.0 → polyxml-0.20.1}/python/polyxml/compat/xsdata.py +0 -0
- {polyxml-0.20.0 → 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.20.
|
|
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.20.
|
|
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.20.
|
|
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.20.
|
|
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.20.
|
|
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
|
|
|
@@ -218,7 +220,7 @@ impl LanguageContext for CSharpLanguageContext {
|
|
|
218
220
|
fn map_type_ref(&self, type_ref: &TypeRef) -> String {
|
|
219
221
|
match type_ref {
|
|
220
222
|
TypeRef::Primitive(prim) => self.map_primitive(*prim).to_string(),
|
|
221
|
-
TypeRef::Named(qname) =>
|
|
223
|
+
TypeRef::Named(qname) => type_ident(qname),
|
|
222
224
|
TypeRef::Boxed(inner) => self.map_type_ref(inner),
|
|
223
225
|
TypeRef::List(inner) => format!("List<{}>", self.map_type_ref(inner)),
|
|
224
226
|
}
|
|
@@ -231,6 +233,12 @@ pub struct CSharpCodegen {
|
|
|
231
233
|
context: CSharpLanguageContext,
|
|
232
234
|
}
|
|
233
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
|
+
|
|
234
242
|
impl CSharpCodegen {
|
|
235
243
|
/// Creates a new C# code generator with the given configuration options.
|
|
236
244
|
pub fn new(options: CSharpOptions) -> Self {
|
|
@@ -242,6 +250,7 @@ impl CSharpCodegen {
|
|
|
242
250
|
|
|
243
251
|
/// Emits all types in the given SchemaIR as a single C# compilation unit.
|
|
244
252
|
pub fn generate_module(&self, ir: &SchemaIR) -> String {
|
|
253
|
+
set_type_name_map(build_type_name_map(ir, to_csharp_type_name));
|
|
245
254
|
let mut out = String::new();
|
|
246
255
|
|
|
247
256
|
if let Some(ref header) = self.options.custom_header {
|
|
@@ -350,7 +359,7 @@ impl CSharpCodegen {
|
|
|
350
359
|
// Enums
|
|
351
360
|
for def in ir.types.values() {
|
|
352
361
|
if let TypeDef::Enum(e) = def {
|
|
353
|
-
let name =
|
|
362
|
+
let name = type_ident(&e.qname);
|
|
354
363
|
writeln!(out, "{}[JsonSerializable(typeof({}))]", indent, name).unwrap();
|
|
355
364
|
}
|
|
356
365
|
}
|
|
@@ -358,7 +367,7 @@ impl CSharpCodegen {
|
|
|
358
367
|
// Simple types
|
|
359
368
|
for def in ir.types.values() {
|
|
360
369
|
if let TypeDef::Simple(s) = def {
|
|
361
|
-
let name =
|
|
370
|
+
let name = type_ident(&s.qname);
|
|
362
371
|
writeln!(out, "{}[JsonSerializable(typeof({}))]", indent, name).unwrap();
|
|
363
372
|
}
|
|
364
373
|
}
|
|
@@ -366,7 +375,7 @@ impl CSharpCodegen {
|
|
|
366
375
|
// Unions
|
|
367
376
|
for def in ir.types.values() {
|
|
368
377
|
if let TypeDef::Union(u) = def {
|
|
369
|
-
let name =
|
|
378
|
+
let name = type_ident(&u.qname);
|
|
370
379
|
writeln!(out, "{}[JsonSerializable(typeof({}))]", indent, name).unwrap();
|
|
371
380
|
}
|
|
372
381
|
}
|
|
@@ -374,7 +383,7 @@ impl CSharpCodegen {
|
|
|
374
383
|
// Structs
|
|
375
384
|
for def in ir.types.values() {
|
|
376
385
|
if let TypeDef::Struct(s) = def {
|
|
377
|
-
let name =
|
|
386
|
+
let name = type_ident(&s.qname);
|
|
378
387
|
writeln!(out, "{}[JsonSerializable(typeof({}))]", indent, name).unwrap();
|
|
379
388
|
writeln!(out, "{}[JsonSerializable(typeof(List<{}>))]", indent, name).unwrap();
|
|
380
389
|
}
|
|
@@ -399,7 +408,7 @@ impl CSharpCodegen {
|
|
|
399
408
|
}
|
|
400
409
|
|
|
401
410
|
fn emit_enum(&self, out: &mut String, e: &EnumDef, indent: &str) {
|
|
402
|
-
let enum_name =
|
|
411
|
+
let enum_name = type_ident(&e.qname);
|
|
403
412
|
if let Some(ref doc) = e.documentation {
|
|
404
413
|
self.emit_docstring(out, doc, indent);
|
|
405
414
|
}
|
|
@@ -482,7 +491,7 @@ impl CSharpCodegen {
|
|
|
482
491
|
|
|
483
492
|
fn emit_simple(&self, out: &mut String, s: &SimpleTypeDef, indent: &str) {
|
|
484
493
|
if !s.facets.is_empty() || !self.options.use_records {
|
|
485
|
-
let type_name =
|
|
494
|
+
let type_name = type_ident(&s.qname);
|
|
486
495
|
let base_type = self.context.map_type_ref(&s.base_type);
|
|
487
496
|
|
|
488
497
|
if let Some(ref doc) = s.documentation {
|
|
@@ -557,7 +566,7 @@ impl CSharpCodegen {
|
|
|
557
566
|
}
|
|
558
567
|
|
|
559
568
|
fn emit_union(&self, out: &mut String, u: &UnionDef, indent: &str) {
|
|
560
|
-
let choice_name =
|
|
569
|
+
let choice_name = type_ident(&u.qname);
|
|
561
570
|
if let Some(ref doc) = u.documentation {
|
|
562
571
|
self.emit_docstring(out, doc, indent);
|
|
563
572
|
}
|
|
@@ -662,7 +671,7 @@ impl CSharpCodegen {
|
|
|
662
671
|
}
|
|
663
672
|
|
|
664
673
|
fn emit_struct(&self, out: &mut String, s: &StructDef, ir: &SchemaIR, indent: &str) {
|
|
665
|
-
let struct_name =
|
|
674
|
+
let struct_name = type_ident(&s.qname);
|
|
666
675
|
if let Some(ref doc) = s.documentation {
|
|
667
676
|
self.emit_docstring(out, doc, indent);
|
|
668
677
|
}
|
|
@@ -690,7 +699,7 @@ impl CSharpCodegen {
|
|
|
690
699
|
let mut base_clause = Vec::new();
|
|
691
700
|
if let Some(ref base_qname) = s.base_type {
|
|
692
701
|
if matches!(ir.types.get(base_qname), Some(TypeDef::Struct(_))) {
|
|
693
|
-
let base_name =
|
|
702
|
+
let base_name = type_ident(base_qname);
|
|
694
703
|
base_clause.push(base_name);
|
|
695
704
|
}
|
|
696
705
|
}
|
|
@@ -816,7 +825,7 @@ impl CSharpCodegen {
|
|
|
816
825
|
}
|
|
817
826
|
|
|
818
827
|
fn emit_struct_validator(&self, out: &mut String, s: &StructDef, indent: &str) {
|
|
819
|
-
let struct_name =
|
|
828
|
+
let struct_name = type_ident(&s.qname);
|
|
820
829
|
let new_kw = if !self.options.use_records {
|
|
821
830
|
if s.base_type.is_some() {
|
|
822
831
|
"override "
|
|
@@ -940,9 +949,9 @@ impl CSharpCodegen {
|
|
|
940
949
|
TypeRef::Primitive(p) => self.context.map_primitive(*p).to_string(),
|
|
941
950
|
TypeRef::Named(qn) => {
|
|
942
951
|
if let Some(TypeDef::Union(u)) = ir.types.get(qn) {
|
|
943
|
-
|
|
952
|
+
type_ident(&u.qname)
|
|
944
953
|
} else {
|
|
945
|
-
|
|
954
|
+
type_ident(qn)
|
|
946
955
|
}
|
|
947
956
|
}
|
|
948
957
|
TypeRef::Boxed(inner) => self.context.map_type_ref(inner),
|
|
@@ -969,7 +978,7 @@ impl CSharpCodegen {
|
|
|
969
978
|
// If the field is a choice (UnionDef), emit XmlElement("branchXml", typeof(BranchType))
|
|
970
979
|
if let TypeRef::Named(ref qname) = f.type_ref {
|
|
971
980
|
if let Some(TypeDef::Union(u)) = ir.types.get(qname) {
|
|
972
|
-
let choice_name =
|
|
981
|
+
let choice_name = type_ident(&u.qname);
|
|
973
982
|
for branch in &u.branches {
|
|
974
983
|
let variant_name = to_csharp_type_name(&branch.variant_name);
|
|
975
984
|
parts.push(format!(
|
|
@@ -3,9 +3,11 @@ use std::fmt::Write as FmtWrite;
|
|
|
3
3
|
use heck::{AsPascalCase, AsSnakeCase};
|
|
4
4
|
use serde::{Deserialize, Serialize};
|
|
5
5
|
|
|
6
|
-
use crate::codegen::{
|
|
6
|
+
use crate::codegen::{
|
|
7
|
+
build_type_name_map, lookup_type_name, sanitize_keyword, set_type_name_map, LanguageContext,
|
|
8
|
+
};
|
|
7
9
|
use crate::ir::{
|
|
8
|
-
EnumDef, FieldDef, FieldKind, PrimitiveType, RestrictionFacets, SchemaIR, SimpleTypeDef,
|
|
10
|
+
EnumDef, FieldDef, FieldKind, PrimitiveType, QName, RestrictionFacets, SchemaIR, SimpleTypeDef,
|
|
9
11
|
StructDef, TypeDef, TypeRef, UnionDef,
|
|
10
12
|
};
|
|
11
13
|
|
|
@@ -124,7 +126,7 @@ impl LanguageContext for GoLanguageContext {
|
|
|
124
126
|
fn map_type_ref(&self, type_ref: &TypeRef) -> String {
|
|
125
127
|
match type_ref {
|
|
126
128
|
TypeRef::Primitive(prim) => self.map_primitive(*prim).to_string(),
|
|
127
|
-
TypeRef::Named(qname) =>
|
|
129
|
+
TypeRef::Named(qname) => type_ident(qname),
|
|
128
130
|
TypeRef::Boxed(inner) => format!("*{}", self.map_type_ref(inner)),
|
|
129
131
|
TypeRef::List(inner) => format!("[]{}", self.map_type_ref(inner)),
|
|
130
132
|
}
|
|
@@ -231,6 +233,12 @@ pub struct GoCodegen {
|
|
|
231
233
|
context: GoLanguageContext,
|
|
232
234
|
}
|
|
233
235
|
|
|
236
|
+
/// Emitted Go 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_go_type_name(&q.local))
|
|
240
|
+
}
|
|
241
|
+
|
|
234
242
|
impl GoCodegen {
|
|
235
243
|
pub fn new(options: GoOptions) -> Self {
|
|
236
244
|
Self {
|
|
@@ -241,6 +249,7 @@ impl GoCodegen {
|
|
|
241
249
|
|
|
242
250
|
/// Generate complete Go module content.
|
|
243
251
|
pub fn generate_module(&self, ir: &SchemaIR) -> String {
|
|
252
|
+
set_type_name_map(build_type_name_map(ir, to_go_type_name));
|
|
244
253
|
let mut body = String::new();
|
|
245
254
|
let mut has_time = false;
|
|
246
255
|
let mut has_fmt = false;
|
|
@@ -394,13 +403,13 @@ impl GoCodegen {
|
|
|
394
403
|
}
|
|
395
404
|
}
|
|
396
405
|
|
|
397
|
-
let type_name =
|
|
406
|
+
let type_name = type_ident(&simple.qname);
|
|
398
407
|
let base_type = self.context.map_type_ref(&simple.base_type);
|
|
399
408
|
writeln!(out, "type {} {}\n", type_name, base_type).unwrap();
|
|
400
409
|
}
|
|
401
410
|
|
|
402
411
|
fn emit_enum(&self, out: &mut String, enum_def: &EnumDef) {
|
|
403
|
-
let enum_name =
|
|
412
|
+
let enum_name = type_ident(&enum_def.qname);
|
|
404
413
|
if let Some(ref doc) = enum_def.documentation {
|
|
405
414
|
for line in doc.lines() {
|
|
406
415
|
writeln!(out, "// {}", line).unwrap();
|
|
@@ -441,7 +450,7 @@ impl GoCodegen {
|
|
|
441
450
|
}
|
|
442
451
|
|
|
443
452
|
fn emit_union(&self, out: &mut String, u: &UnionDef) {
|
|
444
|
-
let choice_name =
|
|
453
|
+
let choice_name = type_ident(&u.qname);
|
|
445
454
|
if let Some(ref doc) = u.documentation {
|
|
446
455
|
for line in doc.lines() {
|
|
447
456
|
writeln!(out, "// {}", line).unwrap();
|
|
@@ -587,7 +596,7 @@ impl GoCodegen {
|
|
|
587
596
|
}
|
|
588
597
|
|
|
589
598
|
fn emit_struct(&self, out: &mut String, s: &StructDef, ir: &SchemaIR) {
|
|
590
|
-
let struct_name =
|
|
599
|
+
let struct_name = type_ident(&s.qname);
|
|
591
600
|
if let Some(ref doc) = s.documentation {
|
|
592
601
|
for line in doc.lines() {
|
|
593
602
|
writeln!(out, "// {}", line).unwrap();
|
|
@@ -620,12 +629,12 @@ impl GoCodegen {
|
|
|
620
629
|
let mut simple_content_base: Option<String> = None;
|
|
621
630
|
if let Some(ref base_qname) = s.base_type {
|
|
622
631
|
if matches!(ir.types.get(base_qname), Some(TypeDef::Struct(_))) {
|
|
623
|
-
let base_name =
|
|
632
|
+
let base_name = type_ident(base_qname);
|
|
624
633
|
writeln!(out, " {}", base_name).unwrap();
|
|
625
634
|
} else if let Some(prim) = PrimitiveType::from_xsd_name(&base_qname.local) {
|
|
626
635
|
simple_content_base = Some(self.context.map_primitive(prim).to_string());
|
|
627
636
|
} else if let Some(TypeDef::Simple(st)) = ir.types.get(base_qname) {
|
|
628
|
-
simple_content_base = Some(
|
|
637
|
+
simple_content_base = Some(type_ident(&st.qname));
|
|
629
638
|
}
|
|
630
639
|
}
|
|
631
640
|
|
|
@@ -744,7 +753,7 @@ impl GoCodegen {
|
|
|
744
753
|
}
|
|
745
754
|
|
|
746
755
|
fn emit_struct_validator(&self, out: &mut String, s: &StructDef) {
|
|
747
|
-
let struct_name =
|
|
756
|
+
let struct_name = type_ident(&s.qname);
|
|
748
757
|
writeln!(out, "func (s {}) Validate() error {{", struct_name).unwrap();
|
|
749
758
|
|
|
750
759
|
let mut has_checks = false;
|
|
@@ -20,13 +20,9 @@ impl JavaCodegen {
|
|
|
20
20
|
_ => Ok(()),
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
let names: HashSet<_> = ir
|
|
24
|
-
.types
|
|
25
|
-
.values()
|
|
26
|
-
.map(|d| to_java_type_name(&d.qname().local))
|
|
27
|
-
.collect();
|
|
23
|
+
let names: HashSet<_> = ir.types.values().map(|d| type_ident(d.qname())).collect();
|
|
28
24
|
for def in ir.types.values() {
|
|
29
|
-
let name =
|
|
25
|
+
let name = type_ident(def.qname());
|
|
30
26
|
if names.contains(&format!("{name}Codec")) {
|
|
31
27
|
return Err(format!(
|
|
32
28
|
"direct codec name {name}Codec collides with a schema type"
|
|
@@ -70,7 +66,7 @@ impl JavaCodegen {
|
|
|
70
66
|
}
|
|
71
67
|
|
|
72
68
|
pub(super) fn generate_codec(&self, def: &TypeDef, ir: &SchemaIR) -> String {
|
|
73
|
-
let name =
|
|
69
|
+
let name = type_ident(def.qname());
|
|
74
70
|
let mut out = String::new();
|
|
75
71
|
self.emit_file_header(&mut out);
|
|
76
72
|
out.push_str("import javax.xml.stream.*;\nimport java.io.*;\n\n");
|
|
@@ -224,7 +220,7 @@ impl JavaCodegen {
|
|
|
224
220
|
}
|
|
225
221
|
|
|
226
222
|
fn emit_read_struct(&self, out: &mut String, s: &StructDef, ir: &SchemaIR) {
|
|
227
|
-
let name =
|
|
223
|
+
let name = type_ident(&s.qname);
|
|
228
224
|
if s.is_abstract && !self.options.use_records {
|
|
229
225
|
out.push_str(" throw new XMLStreamException(\"Cannot instantiate abstract XML type without a concrete codec\");\n");
|
|
230
226
|
return;
|
|
@@ -400,7 +396,7 @@ impl JavaCodegen {
|
|
|
400
396
|
self.emit_write_value(out, inner, value, local, ns, ir, indent)
|
|
401
397
|
}
|
|
402
398
|
TypeRef::Named(q) => {
|
|
403
|
-
let name =
|
|
399
|
+
let name = type_ident(q);
|
|
404
400
|
let _ = writeln!(
|
|
405
401
|
out,
|
|
406
402
|
"{indent}{name}Codec.writeXml({value}, writer, {local:?}, {ns:?});"
|
|
@@ -415,7 +411,7 @@ impl JavaCodegen {
|
|
|
415
411
|
|
|
416
412
|
fn read_value(&self, ty: &TypeRef, ir: &SchemaIR) -> String {
|
|
417
413
|
match ty {
|
|
418
|
-
TypeRef::Named(q) => format!("{}Codec.readXml(reader)",
|
|
414
|
+
TypeRef::Named(q) => format!("{}Codec.readXml(reader)", type_ident(q)),
|
|
419
415
|
TypeRef::Boxed(t) => self.read_value(t, ir),
|
|
420
416
|
_ => self.parse_scalar(ty, "reader.getElementText()", ir),
|
|
421
417
|
}
|
|
@@ -431,11 +427,11 @@ impl JavaCodegen {
|
|
|
431
427
|
}
|
|
432
428
|
TypeRef::Named(q) => match ir.types.get(q) {
|
|
433
429
|
Some(TypeDef::Enum(_)) => {
|
|
434
|
-
format!("{}.fromValue({raw})",
|
|
430
|
+
format!("{}.fromValue({raw})", type_ident(q))
|
|
435
431
|
}
|
|
436
432
|
Some(TypeDef::Simple(s)) => format!(
|
|
437
433
|
"new {}({})",
|
|
438
|
-
|
|
434
|
+
type_ident(q),
|
|
439
435
|
self.parse_scalar(&s.base_type, raw, ir)
|
|
440
436
|
),
|
|
441
437
|
_ => "null".into(),
|
|
@@ -7,9 +7,11 @@ use std::fmt::Write as FmtWrite;
|
|
|
7
7
|
use heck::{AsLowerCamelCase, AsPascalCase, AsShoutySnakeCase};
|
|
8
8
|
use serde::{Deserialize, Serialize};
|
|
9
9
|
|
|
10
|
-
use crate::codegen::{
|
|
10
|
+
use crate::codegen::{
|
|
11
|
+
build_type_name_map, lookup_type_name, sanitize_keyword, set_type_name_map, LanguageContext,
|
|
12
|
+
};
|
|
11
13
|
use crate::ir::{
|
|
12
|
-
EnumDef, PrimitiveType, RestrictionFacets, SchemaIR, SimpleTypeDef, StructDef, TypeDef,
|
|
14
|
+
EnumDef, PrimitiveType, QName, RestrictionFacets, SchemaIR, SimpleTypeDef, StructDef, TypeDef,
|
|
13
15
|
TypeRef, UnionDef,
|
|
14
16
|
};
|
|
15
17
|
|
|
@@ -134,7 +136,7 @@ impl LanguageContext for JavaLanguageContext {
|
|
|
134
136
|
fn map_type_ref(&self, type_ref: &TypeRef) -> String {
|
|
135
137
|
match type_ref {
|
|
136
138
|
TypeRef::Primitive(prim) => self.map_primitive(*prim).to_string(),
|
|
137
|
-
TypeRef::Named(qname) =>
|
|
139
|
+
TypeRef::Named(qname) => type_ident(qname),
|
|
138
140
|
TypeRef::Boxed(inner) | TypeRef::List(inner) => {
|
|
139
141
|
let inner_str = self.boxed_type(inner);
|
|
140
142
|
if matches!(type_ref, TypeRef::List(_)) {
|
|
@@ -172,7 +174,7 @@ impl JavaLanguageContext {
|
|
|
172
174
|
PrimitiveType::Base64Binary | PrimitiveType::HexBinary => "byte[]".to_string(),
|
|
173
175
|
_ => self.map_primitive(*prim).to_string(),
|
|
174
176
|
},
|
|
175
|
-
TypeRef::Named(qname) =>
|
|
177
|
+
TypeRef::Named(qname) => type_ident(qname),
|
|
176
178
|
TypeRef::Boxed(inner) => self.boxed_type(inner),
|
|
177
179
|
TypeRef::List(inner) => format!("java.util.List<{}>", self.boxed_type(inner)),
|
|
178
180
|
}
|
|
@@ -205,6 +207,12 @@ pub fn to_java_type_name(name: &str) -> String {
|
|
|
205
207
|
sanitize_keyword(&sanitized, "java")
|
|
206
208
|
}
|
|
207
209
|
|
|
210
|
+
/// Emitted Java identifier for a named type, disambiguated across
|
|
211
|
+
/// namespaces for the IR currently being generated (issue #51 item 3).
|
|
212
|
+
pub(super) fn type_ident(q: &QName) -> String {
|
|
213
|
+
lookup_type_name(q, || to_java_type_name(&q.local))
|
|
214
|
+
}
|
|
215
|
+
|
|
208
216
|
/// Convert an XML enumeration variant name to SCREAMING_SNAKE_CASE for Java enum constants.
|
|
209
217
|
pub fn to_java_enum_constant(name: &str) -> String {
|
|
210
218
|
let raw = AsShoutySnakeCase(name).to_string();
|
|
@@ -234,6 +242,7 @@ impl JavaCodegen {
|
|
|
234
242
|
|
|
235
243
|
/// Generate individual compilation units (`{TypeName}.java`), one for each schema type.
|
|
236
244
|
pub fn generate_files(&self, ir: &SchemaIR) -> Vec<(String, String)> {
|
|
245
|
+
set_type_name_map(build_type_name_map(ir, to_java_type_name));
|
|
237
246
|
let mut files = Vec::new();
|
|
238
247
|
|
|
239
248
|
for type_def in ir.types.values() {
|
|
@@ -253,6 +262,7 @@ impl JavaCodegen {
|
|
|
253
262
|
|
|
254
263
|
/// Generate a single outer class (`{outer_class_name}.java`) enclosing all types as static members.
|
|
255
264
|
pub fn generate_module(&self, ir: &SchemaIR, outer_class_name: &str) -> String {
|
|
265
|
+
set_type_name_map(build_type_name_map(ir, to_java_type_name));
|
|
256
266
|
let mut out = String::new();
|
|
257
267
|
|
|
258
268
|
self.emit_file_header(&mut out);
|
|
@@ -368,22 +378,22 @@ impl JavaCodegen {
|
|
|
368
378
|
let mut out = String::new();
|
|
369
379
|
let type_name = match type_def {
|
|
370
380
|
TypeDef::Struct(s) => {
|
|
371
|
-
let name =
|
|
381
|
+
let name = type_ident(&s.qname);
|
|
372
382
|
self.emit_struct(&mut out, s, &name, indent, ir);
|
|
373
383
|
name
|
|
374
384
|
}
|
|
375
385
|
TypeDef::Enum(e) => {
|
|
376
|
-
let name =
|
|
386
|
+
let name = type_ident(&e.qname);
|
|
377
387
|
self.emit_enum(&mut out, e, &name, indent);
|
|
378
388
|
name
|
|
379
389
|
}
|
|
380
390
|
TypeDef::Union(u) => {
|
|
381
|
-
let name =
|
|
391
|
+
let name = type_ident(&u.qname);
|
|
382
392
|
self.emit_union(&mut out, u, &name, indent);
|
|
383
393
|
name
|
|
384
394
|
}
|
|
385
395
|
TypeDef::Simple(s) => {
|
|
386
|
-
let name =
|
|
396
|
+
let name = type_ident(&s.qname);
|
|
387
397
|
self.emit_simple(&mut out, s, &name, indent);
|
|
388
398
|
name
|
|
389
399
|
}
|
|
@@ -160,7 +160,7 @@ impl JavaCodegen {
|
|
|
160
160
|
.as_ref()
|
|
161
161
|
.filter(|q| matches!(ir.types.get(q), Some(TypeDef::Struct(_))));
|
|
162
162
|
let extends = base
|
|
163
|
-
.map(|q| format!(" extends {}",
|
|
163
|
+
.map(|q| format!(" extends {}", type_ident(q)))
|
|
164
164
|
.unwrap_or_default();
|
|
165
165
|
let nested = if indent.is_empty() { "" } else { "static " };
|
|
166
166
|
let abstract_kw = if s.is_abstract { "abstract " } else { "" };
|
|
@@ -258,7 +258,7 @@ impl JavaCodegen {
|
|
|
258
258
|
};
|
|
259
259
|
let extends = base
|
|
260
260
|
.map(|q| {
|
|
261
|
-
let n =
|
|
261
|
+
let n = type_ident(q);
|
|
262
262
|
format!(" extends {n}.{n}Builder")
|
|
263
263
|
})
|
|
264
264
|
.unwrap_or_default();
|