aas-core-codegen 0.0.16__py3-none-any.whl
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.
- aas_core_codegen/__init__.py +6 -0
- aas_core_codegen/__main__.py +8 -0
- aas_core_codegen/common.py +500 -0
- aas_core_codegen/cpp/__init__.py +1 -0
- aas_core_codegen/cpp/aas_common/__init__.py +6 -0
- aas_core_codegen/cpp/aas_common/_generate.py +713 -0
- aas_core_codegen/cpp/common.py +681 -0
- aas_core_codegen/cpp/constants/__init__.py +6 -0
- aas_core_codegen/cpp/constants/_generate.py +568 -0
- aas_core_codegen/cpp/description.py +654 -0
- aas_core_codegen/cpp/enhancing/__init__.py +4 -0
- aas_core_codegen/cpp/enhancing/_generate.py +993 -0
- aas_core_codegen/cpp/iteration/__init__.py +6 -0
- aas_core_codegen/cpp/iteration/_generate.py +2332 -0
- aas_core_codegen/cpp/jsonization/__init__.py +6 -0
- aas_core_codegen/cpp/jsonization/_generate.py +2619 -0
- aas_core_codegen/cpp/main.py +694 -0
- aas_core_codegen/cpp/naming.py +170 -0
- aas_core_codegen/cpp/optionaling.py +557 -0
- aas_core_codegen/cpp/pattern/__init__.py +6 -0
- aas_core_codegen/cpp/pattern/_generate.py +508 -0
- aas_core_codegen/cpp/revm/__init__.py +6 -0
- aas_core_codegen/cpp/revm/_generate.py +1149 -0
- aas_core_codegen/cpp/stringification/__init__.py +5 -0
- aas_core_codegen/cpp/stringification/_generate.py +955 -0
- aas_core_codegen/cpp/structure/__init__.py +7 -0
- aas_core_codegen/cpp/structure/_generate.py +1503 -0
- aas_core_codegen/cpp/transpilation.py +1383 -0
- aas_core_codegen/cpp/unrolling.py +159 -0
- aas_core_codegen/cpp/verification/__init__.py +6 -0
- aas_core_codegen/cpp/verification/_generate.py +3073 -0
- aas_core_codegen/cpp/visitation/__init__.py +6 -0
- aas_core_codegen/cpp/visitation/_generate.py +521 -0
- aas_core_codegen/cpp/wstringification/__init__.py +5 -0
- aas_core_codegen/cpp/wstringification/_generate.py +586 -0
- aas_core_codegen/cpp/xmlization/__init__.py +6 -0
- aas_core_codegen/cpp/xmlization/_generate.py +5373 -0
- aas_core_codegen/cpp/yielding.py +201 -0
- aas_core_codegen/csharp/__init__.py +1 -0
- aas_core_codegen/csharp/common.py +224 -0
- aas_core_codegen/csharp/constants/__init__.py +5 -0
- aas_core_codegen/csharp/constants/_generate.py +409 -0
- aas_core_codegen/csharp/copying/__init__.py +4 -0
- aas_core_codegen/csharp/copying/_generate.py +498 -0
- aas_core_codegen/csharp/description.py +1103 -0
- aas_core_codegen/csharp/enhancing/__init__.py +4 -0
- aas_core_codegen/csharp/enhancing/_generate.py +667 -0
- aas_core_codegen/csharp/jsonization/__init__.py +4 -0
- aas_core_codegen/csharp/jsonization/_generate.py +1630 -0
- aas_core_codegen/csharp/main.py +421 -0
- aas_core_codegen/csharp/naming.py +157 -0
- aas_core_codegen/csharp/reporting/__init__.py +4 -0
- aas_core_codegen/csharp/reporting/_generate.py +266 -0
- aas_core_codegen/csharp/stringification/__init__.py +4 -0
- aas_core_codegen/csharp/stringification/_generate.py +243 -0
- aas_core_codegen/csharp/structure/__init__.py +6 -0
- aas_core_codegen/csharp/structure/_generate.py +1341 -0
- aas_core_codegen/csharp/transpilation.py +990 -0
- aas_core_codegen/csharp/unrolling.py +211 -0
- aas_core_codegen/csharp/verification/__init__.py +6 -0
- aas_core_codegen/csharp/verification/_generate.py +1457 -0
- aas_core_codegen/csharp/visitation/__init__.py +5 -0
- aas_core_codegen/csharp/visitation/_generate.py +579 -0
- aas_core_codegen/csharp/xmlization/__init__.py +4 -0
- aas_core_codegen/csharp/xmlization/_generate.py +1980 -0
- aas_core_codegen/golang/__init__.py +1 -0
- aas_core_codegen/golang/aas_common/__init__.py +4 -0
- aas_core_codegen/golang/aas_common/_generate.py +152 -0
- aas_core_codegen/golang/common.py +303 -0
- aas_core_codegen/golang/constants/__init__.py +5 -0
- aas_core_codegen/golang/constants/_generate.py +339 -0
- aas_core_codegen/golang/description.py +501 -0
- aas_core_codegen/golang/enhancing/__init__.py +4 -0
- aas_core_codegen/golang/enhancing/_generate.py +527 -0
- aas_core_codegen/golang/jsonization/__init__.py +4 -0
- aas_core_codegen/golang/jsonization/_generate.py +1740 -0
- aas_core_codegen/golang/main.py +368 -0
- aas_core_codegen/golang/naming.py +412 -0
- aas_core_codegen/golang/pointering.py +631 -0
- aas_core_codegen/golang/reporting/__init__.py +4 -0
- aas_core_codegen/golang/reporting/_generate.py +218 -0
- aas_core_codegen/golang/stringification/__init__.py +4 -0
- aas_core_codegen/golang/stringification/_generate.py +394 -0
- aas_core_codegen/golang/structure/__init__.py +6 -0
- aas_core_codegen/golang/structure/_generate.py +1493 -0
- aas_core_codegen/golang/transpilation.py +1191 -0
- aas_core_codegen/golang/unrolling.py +159 -0
- aas_core_codegen/golang/verification/__init__.py +6 -0
- aas_core_codegen/golang/verification/_generate.py +1513 -0
- aas_core_codegen/golang/xmlization/__init__.py +4 -0
- aas_core_codegen/golang/xmlization/_generate.py +2507 -0
- aas_core_codegen/infer_for_schema/__init__.py +21 -0
- aas_core_codegen/infer_for_schema/_inline.py +693 -0
- aas_core_codegen/infer_for_schema/_len.py +527 -0
- aas_core_codegen/infer_for_schema/_pattern.py +311 -0
- aas_core_codegen/infer_for_schema/_set.py +394 -0
- aas_core_codegen/infer_for_schema/_stringify.py +201 -0
- aas_core_codegen/infer_for_schema/_types.py +135 -0
- aas_core_codegen/infer_for_schema/match.py +122 -0
- aas_core_codegen/intermediate/__init__.py +78 -0
- aas_core_codegen/intermediate/_hierarchy.py +397 -0
- aas_core_codegen/intermediate/_stringify.py +989 -0
- aas_core_codegen/intermediate/_translate.py +5128 -0
- aas_core_codegen/intermediate/_types.py +2901 -0
- aas_core_codegen/intermediate/construction.py +750 -0
- aas_core_codegen/intermediate/doc.py +344 -0
- aas_core_codegen/intermediate/pattern_verification.py +428 -0
- aas_core_codegen/intermediate/revm.py +985 -0
- aas_core_codegen/intermediate/type_inference.py +2266 -0
- aas_core_codegen/java/__init__.py +1 -0
- aas_core_codegen/java/common.py +197 -0
- aas_core_codegen/java/constants/__init__.py +5 -0
- aas_core_codegen/java/constants/_generate.py +334 -0
- aas_core_codegen/java/copying/__init__.py +4 -0
- aas_core_codegen/java/copying/_generate.py +502 -0
- aas_core_codegen/java/description.py +774 -0
- aas_core_codegen/java/enhancing/__init__.py +4 -0
- aas_core_codegen/java/enhancing/_generate.py +820 -0
- aas_core_codegen/java/generation/__init__.py +5 -0
- aas_core_codegen/java/generation/_generate.py +285 -0
- aas_core_codegen/java/jsonization/__init__.py +4 -0
- aas_core_codegen/java/jsonization/_generate.py +1472 -0
- aas_core_codegen/java/main.py +438 -0
- aas_core_codegen/java/naming.py +187 -0
- aas_core_codegen/java/optional.py +514 -0
- aas_core_codegen/java/reporting/__init__.py +4 -0
- aas_core_codegen/java/reporting/_generate.py +248 -0
- aas_core_codegen/java/stringification/__init__.py +4 -0
- aas_core_codegen/java/stringification/_generate.py +212 -0
- aas_core_codegen/java/structure/__init__.py +6 -0
- aas_core_codegen/java/structure/_generate.py +1767 -0
- aas_core_codegen/java/transpilation.py +1111 -0
- aas_core_codegen/java/verification/__init__.py +6 -0
- aas_core_codegen/java/verification/_generate.py +1536 -0
- aas_core_codegen/java/visitation/__init__.py +5 -0
- aas_core_codegen/java/visitation/_generate.py +689 -0
- aas_core_codegen/java/xmlization/__init__.py +4 -0
- aas_core_codegen/java/xmlization/_generate.py +2274 -0
- aas_core_codegen/jsonld/__init__.py +1 -0
- aas_core_codegen/jsonld/main.py +455 -0
- aas_core_codegen/jsonschema/__init__.py +1 -0
- aas_core_codegen/jsonschema/main.py +982 -0
- aas_core_codegen/main.py +245 -0
- aas_core_codegen/naming.py +133 -0
- aas_core_codegen/opcua/__init__.py +1 -0
- aas_core_codegen/opcua/main.py +1525 -0
- aas_core_codegen/opcua/naming.py +126 -0
- aas_core_codegen/parse/__init__.py +46 -0
- aas_core_codegen/parse/_rules.py +796 -0
- aas_core_codegen/parse/_stringify.py +532 -0
- aas_core_codegen/parse/_translate.py +3940 -0
- aas_core_codegen/parse/_types.py +973 -0
- aas_core_codegen/parse/retree/__init__.py +46 -0
- aas_core_codegen/parse/retree/_fix.py +434 -0
- aas_core_codegen/parse/retree/_parse.py +1143 -0
- aas_core_codegen/parse/retree/_render.py +298 -0
- aas_core_codegen/parse/retree/_stringify.py +199 -0
- aas_core_codegen/parse/retree/_types.py +362 -0
- aas_core_codegen/parse/retree/_visitor.py +70 -0
- aas_core_codegen/parse/tree.py +1303 -0
- aas_core_codegen/protobuf/__init__.py +1 -0
- aas_core_codegen/protobuf/common.py +225 -0
- aas_core_codegen/protobuf/description.py +1102 -0
- aas_core_codegen/protobuf/main.py +115 -0
- aas_core_codegen/protobuf/naming.py +143 -0
- aas_core_codegen/protobuf/structure/__init__.py +6 -0
- aas_core_codegen/protobuf/structure/_generate.py +502 -0
- aas_core_codegen/py.typed +1 -0
- aas_core_codegen/python/__init__.py +1 -0
- aas_core_codegen/python/aas_common/__init__.py +4 -0
- aas_core_codegen/python/aas_common/_generate.py +63 -0
- aas_core_codegen/python/common.py +406 -0
- aas_core_codegen/python/constants/__init__.py +5 -0
- aas_core_codegen/python/constants/_generate.py +377 -0
- aas_core_codegen/python/description.py +508 -0
- aas_core_codegen/python/jsonization/__init__.py +4 -0
- aas_core_codegen/python/jsonization/_generate.py +1391 -0
- aas_core_codegen/python/main.py +323 -0
- aas_core_codegen/python/naming.py +255 -0
- aas_core_codegen/python/stringification/__init__.py +4 -0
- aas_core_codegen/python/stringification/_generate.py +129 -0
- aas_core_codegen/python/structure/__init__.py +6 -0
- aas_core_codegen/python/structure/_generate.py +1801 -0
- aas_core_codegen/python/transpilation.py +958 -0
- aas_core_codegen/python/unrolling.py +156 -0
- aas_core_codegen/python/verification/__init__.py +6 -0
- aas_core_codegen/python/verification/_generate.py +1471 -0
- aas_core_codegen/python/xmlization/__init__.py +4 -0
- aas_core_codegen/python/xmlization/_generate.py +3003 -0
- aas_core_codegen/python_protobuf/__init__.py +1 -0
- aas_core_codegen/python_protobuf/main.py +1424 -0
- aas_core_codegen/python_protobuf/naming.py +85 -0
- aas_core_codegen/rdf_shacl/__init__.py +1 -0
- aas_core_codegen/rdf_shacl/_description.py +351 -0
- aas_core_codegen/rdf_shacl/common.py +206 -0
- aas_core_codegen/rdf_shacl/main.py +114 -0
- aas_core_codegen/rdf_shacl/naming.py +145 -0
- aas_core_codegen/rdf_shacl/rdf.py +435 -0
- aas_core_codegen/rdf_shacl/shacl.py +453 -0
- aas_core_codegen/run.py +124 -0
- aas_core_codegen/smoke/__init__.py +1 -0
- aas_core_codegen/smoke/main.py +219 -0
- aas_core_codegen/specific_implementations.py +72 -0
- aas_core_codegen/stringify.py +333 -0
- aas_core_codegen/typescript/__init__.py +1 -0
- aas_core_codegen/typescript/aas_common/__init__.py +4 -0
- aas_core_codegen/typescript/aas_common/_generate.py +472 -0
- aas_core_codegen/typescript/common.py +340 -0
- aas_core_codegen/typescript/constants/__init__.py +5 -0
- aas_core_codegen/typescript/constants/_generate.py +347 -0
- aas_core_codegen/typescript/description.py +530 -0
- aas_core_codegen/typescript/jsonization/__init__.py +4 -0
- aas_core_codegen/typescript/jsonization/_generate.py +1510 -0
- aas_core_codegen/typescript/main.py +258 -0
- aas_core_codegen/typescript/naming.py +189 -0
- aas_core_codegen/typescript/stringification/__init__.py +4 -0
- aas_core_codegen/typescript/stringification/_generate.py +367 -0
- aas_core_codegen/typescript/structure/__init__.py +6 -0
- aas_core_codegen/typescript/structure/_generate.py +2500 -0
- aas_core_codegen/typescript/transpilation.py +1051 -0
- aas_core_codegen/typescript/unrolling.py +159 -0
- aas_core_codegen/typescript/verification/__init__.py +6 -0
- aas_core_codegen/typescript/verification/_generate.py +1578 -0
- aas_core_codegen/xsd/__init__.py +1 -0
- aas_core_codegen/xsd/main.py +1187 -0
- aas_core_codegen/xsd/naming.py +83 -0
- aas_core_codegen/yielding/__init__.py +1 -0
- aas_core_codegen/yielding/flow.py +139 -0
- aas_core_codegen/yielding/linear.py +754 -0
- aas_core_codegen-0.0.16.dist-info/METADATA +211 -0
- aas_core_codegen-0.0.16.dist-info/RECORD +604 -0
- aas_core_codegen-0.0.16.dist-info/WHEEL +5 -0
- aas_core_codegen-0.0.16.dist-info/entry_points.txt +3 -0
- aas_core_codegen-0.0.16.dist-info/licenses/AUTHORS +9 -0
- aas_core_codegen-0.0.16.dist-info/licenses/LICENSE +23 -0
- aas_core_codegen-0.0.16.dist-info/top_level.txt +2 -0
- dev/continuous_integration/__init__.py +1 -0
- dev/continuous_integration/check_help_in_readme.py +208 -0
- dev/continuous_integration/check_init_and_pyproject_consistent.py +154 -0
- dev/continuous_integration/precommit.py +400 -0
- dev/dev_scripts/__init__.py +1 -0
- dev/dev_scripts/compare_rendered_regexes_against_source_py.py +42 -0
- dev/dev_scripts/copy_to_aas_core3_cpp.py +100 -0
- dev/dev_scripts/copy_to_aas_core3_java.py +90 -0
- dev/dev_scripts/download_latest_aas_core_meta_v3.py +114 -0
- dev/dev_scripts/draw_bipartite_graph_based_on_lines.py +37 -0
- dev/dev_scripts/run_tests_with_rerecord.py +69 -0
- dev/dev_scripts/update_to_aas_core_meta.py +174 -0
- dev/integration_tests/input/jsonschema/boilerplate/main.py +55 -0
- dev/integration_tests/input/meta_model.py +38 -0
- dev/integration_tests/input/python/boilerplate/main.py +153 -0
- dev/integration_tests/main.py +258 -0
- dev/test_data/csharp/test_structure/concrete_class_with_descendants/meta_model.py +15 -0
- dev/test_data/csharp/test_structure/constructor_without_arguments/all_properties_optional/meta_model.py +9 -0
- dev/test_data/csharp/test_structure/constructor_without_arguments/no_properties/meta_model.py +6 -0
- dev/test_data/csharp/test_verification/builtin_functions/len/on_list/meta_model.py +20 -0
- dev/test_data/csharp/test_verification/builtin_functions/len/on_str/meta_model.py +16 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_prefix/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_suffix/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_group_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_the_middle/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_union/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/single_utf32_literal/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_within_group/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_without_group/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_beginning/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_end/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/in_the_middle/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/multiple/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/mixed_with_non_utf32/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/more_than_two_high_surrogates/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges_mixed_with_non_utf32/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/two_high_surrogates/meta_model.py +8 -0
- dev/test_data/intermediate/expected/class/empty/meta_model.py +6 -0
- dev/test_data/intermediate/expected/class/implementation_specific_method/meta_model.py +8 -0
- dev/test_data/intermediate/expected/class/inheritance/meta_model.py +41 -0
- dev/test_data/intermediate/expected/class/methods_with_contracts/meta_model.py +15 -0
- dev/test_data/intermediate/expected/class/only_method_no_property/meta_model.py +7 -0
- dev/test_data/intermediate/expected/class/only_property_no_method/meta_model.py +9 -0
- dev/test_data/intermediate/expected/constant/constant_set/of_enum/meta_model.py +12 -0
- dev/test_data/intermediate/expected/constant/constant_set/of_str/meta_model.py +4 -0
- dev/test_data/intermediate/expected/constant/constant_set/with_description/meta_model.py +6 -0
- dev/test_data/intermediate/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
- dev/test_data/intermediate/expected/constant/constant_str/only_value/meta_model.py +7 -0
- dev/test_data/intermediate/expected/constant/constant_str/with_description/meta_model.py +5 -0
- dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_in_literal/meta_model.py +20 -0
- dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_outside_literal/meta_model.py +20 -0
- dev/test_data/intermediate/expected/empty/meta_model.py +2 -0
- dev/test_data/intermediate/expected/enumeration/meta_model.py +9 -0
- dev/test_data/intermediate/expected/interface/basic/meta_model.py +14 -0
- dev/test_data/intermediate/expected/interface/empty/meta_model.py +7 -0
- dev/test_data/intermediate/expected/interface/inheritance/meta_model.py +27 -0
- dev/test_data/intermediate/expected/interface/method_signature/meta_model.py +10 -0
- dev/test_data/intermediate/expected/interface/only_constructor/meta_model.py +11 -0
- dev/test_data/intermediate/expected/method/non_mutating/implementation_specific/meta_model.py +12 -0
- dev/test_data/intermediate/expected/method/non_mutating/understood/meta_model.py +11 -0
- dev/test_data/intermediate/expected/type_annotation/atomic/meta_model.py +9 -0
- dev/test_data/intermediate/expected/type_annotation/subscripted/class/meta_model.py +13 -0
- dev/test_data/intermediate/expected/type_annotation/subscripted/primitive/meta_model.py +9 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/enumeration_literals_in_subset_outside_of_superset/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/invalid_literal/meta_model.py +11 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_between_enumeration_and_literal/meta_model.py +30 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_in_enumerations_between_subset_and_superset/meta_model.py +21 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/literals_in_subset_outside_of_superset/meta_model.py +18 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/mismatch_between_type_annotation_and_literals/meta_model.py +10 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/superset_and_subset_mismatch_in_type/meta_model.py +12 -0
- dev/test_data/intermediate/unexpected/constraints/dangling_constraintref/meta_model.py +18 -0
- dev/test_data/intermediate/unexpected/constraints/duplicate_constraints/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/documentation/unexpected_documentation_elements/meta_model.py +34 -0
- dev/test_data/intermediate/unexpected/invariant/class_invariant_uses_re/meta_model.py +10 -0
- dev/test_data/intermediate/unexpected/invariant/invariant_of_constrained_primitive_uses_re/meta_model.py +7 -0
- dev/test_data/intermediate/unexpected/invariant/unexpected_argument_count_to_len/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/invariant/unhandled_built_in_function/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/method_definitions/non_constant_default/meta_model.py +7 -0
- dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/default_non_none/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/no_default/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/after_inheritance/meta_model.py +58 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/meta_model.py +9 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/within_class/meta_model.py +22 -0
- dev/test_data/jsonschema/test_main/regression_when_len_constraints_on_inherited_property/meta_model.py +28 -0
- dev/test_data/opcua/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/opcua/test_main/classes_with_invariants/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_descendant/meta_model.py +27 -0
- dev/test_data/opcua/test_main/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_list_of_instances/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/opcua/test_main/concrete_class_with_string/meta_model.py +13 -0
- dev/test_data/opcua/test_main/constrained_primitive/meta_model.py +20 -0
- dev/test_data/opcua/test_main/multiple_inheritance/meta_model.py +25 -0
- dev/test_data/parse/expected/constant/constant_set/of_enum/meta_model.py +12 -0
- dev/test_data/parse/expected/constant/constant_set/of_str/meta_model.py +4 -0
- dev/test_data/parse/expected/constant/constant_set/with_description/meta_model.py +6 -0
- dev/test_data/parse/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
- dev/test_data/parse/expected/constant/constant_str/only_value/meta_model.py +7 -0
- dev/test_data/parse/expected/constant/constant_str/with_description/meta_model.py +5 -0
- dev/test_data/parse/expected/enum/ok/meta_model.py +15 -0
- dev/test_data/parse/expected/implementation_specific_class/properties_and_methods_in_implementation_specific_class/meta_model.py +17 -0
- dev/test_data/parse/expected/inheritance/basic/meta_model.py +11 -0
- dev/test_data/parse/expected/inheritance/diamond/meta_model.py +26 -0
- dev/test_data/parse/expected/inheritance/inheritance_from_concrete_class/meta_model.py +10 -0
- dev/test_data/parse/expected/invariants/in_relation/meta_model.py +16 -0
- dev/test_data/parse/expected/method/arguments/meta_model.py +7 -0
- dev/test_data/parse/expected/method/basic/meta_model.py +7 -0
- dev/test_data/parse/expected/method/contracts/condition_as_keyword_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/condition_as_positional_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/description_as_keyword_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/description_as_positional_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/multiple_contracts_in_order/meta_model.py +17 -0
- dev/test_data/parse/expected/method/contracts/postcondition/basic/meta_model.py +10 -0
- dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_keyword_arguments/meta_model.py +9 -0
- dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_positional_arguments/meta_model.py +9 -0
- dev/test_data/parse/expected/method/default/meta_model.py +9 -0
- dev/test_data/parse/expected/method/description/meta_model.py +8 -0
- dev/test_data/parse/expected/method/is_implementation_specific/meta_model.py +8 -0
- dev/test_data/parse/expected/method/non_mutating/meta_model.py +11 -0
- dev/test_data/parse/expected/method/returns_none/meta_model.py +7 -0
- dev/test_data/parse/expected/method/returns_something/meta_model.py +7 -0
- dev/test_data/parse/expected/single_class/description/meta_model.py +12 -0
- dev/test_data/parse/expected/single_class/empty/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/description/meta_model.py +14 -0
- dev/test_data/parse/expected/single_class/property/mandatory/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/optional/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/recursion_to_entity/meta_model.py +6 -0
- dev/test_data/parse/unexpected/class_decorators/non_name_decorator/meta_model.py +7 -0
- dev/test_data/parse/unexpected/class_decorators/unknown_decorator/meta_model.py +7 -0
- dev/test_data/parse/unexpected/class_definitions/is_abstract_and_implementation_specific/meta_model.py +8 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_before_a_method/meta_model.py +11 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_for_a_pass/meta_model.py +9 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_double_description_for_a_property/meta_model.py +10 -0
- dev/test_data/parse/unexpected/class_inheritances/inheriting_from_implementation_specific_parent/meta_model.py +20 -0
- dev/test_data/parse/unexpected/class_inheritances/non_name_super_class/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/expression_as_assignment_value/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/non_assignment/meta_model.py +8 -0
- dev/test_data/parse/unexpected/enum/non_string_literal/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/unexpected_inheritance/meta_model.py +6 -0
- dev/test_data/parse/unexpected/method_contracts/contract/non_lambda_condition/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/non_string_literal_description/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/without_any_arguments/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/without_condition/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/postcondition/OLD_in_postcondition_without_snapshot/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/postcondition/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/precondition/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/capture_not_a_lambda/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/invalid_name/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/name_not_a_string_literal/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_capture/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_name/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_constructor/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_verification_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_name_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/unknown_call_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/unknown_name_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_definitions/argument_with_final/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/argument_without_a_type_annotation/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/default_for_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/dunder/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/init_with_return_type/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_keyword_only_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_positional_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_type_annotation_for_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_variable_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_variable_keyword_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_type_annotation_for_result/meta_model.py +7 -0
- dev/test_data/parse/unexpected/property_definitions/final_without_subscript/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/nested_final/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/non_simple/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/unexpected_assignment/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/unexpected_non_name_property/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/without_type_annotation/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/constant_set_with_a_non_set_subset/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_inheritance/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_a_property/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_an_argument/meta_model.py +7 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_constant_set/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_subset_in_constant_set/meta_model.py +4 -0
- dev/test_data/parse/unexpected/symbol_table/inheritance_from_non_class/meta_model.py +10 -0
- dev/test_data/parse_retree/expected/character_set/common_escaping/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/double_caret/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/multiple_ranges/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/suffix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/escape_first_caret/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/literals_which_need_no_escaping_in_characters_set_but_need_escaping_outside/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/multiple_ranges/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/single_literal/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/single_range/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/only_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/prefix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/suffix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/dot/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group_in_a_group/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group_of_union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/regex/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/expected/escaped_literals/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/at_the_beginning/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/at_the_end/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/single_formatted_value/source.py +1 -0
- dev/test_data/parse_retree/expected/literal/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_least_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_least_one/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_most_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/exactly_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/maybe/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/zero_or_more/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_one/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_most_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/exactly_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/maybe/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/zero_or_more/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_character_set/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_formatted_value/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_group/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_literal/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/double_end_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/double_start_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/end_symbol_in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/only_start_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/only_stop_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_at_the_beginning/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/stop_symbol_at_the_end/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_character_sets/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_groups/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_string_literals/source.py +1 -0
- dev/test_data/parse_retree/expected/union/within_group/source.py +1 -0
- dev/test_data/parse_retree/expected/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/Uxxxxxxxx_out_of_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/only_backslash/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_Uxxxxxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_uxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unexpected_escaping/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/Uxxxxxxxx_out_of_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/only_backslash/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_Uxxxxxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_uxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unexpected_escaping/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_character_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/at_least_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/between_3_and_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/exactly_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unhandled_group_directives/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/character_set/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/group/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/group_of_union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_comma/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_number_and_comma/source.py +1 -0
- dev/test_data/proto/test_main/expected/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_descendants/meta_model.py +30 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_list_of_instances/meta_model.py +21 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/expected_output/pbization.py +532 -0
- dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/expected_output/pbization.py +527 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/meta_model.py +27 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_enum/expected_output/pbization.py +290 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/expected_output/pbization.py +328 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/meta_model.py +23 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/expected_output/pbization.py +274 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/rdf_shacl/test_main/expected/regression_when_lang_string_class_is_missing/meta_model.py +29 -0
- dev/test_data/rdf_shacl/test_main/expected/regression_when_len_constraints_on_inherited_property/meta_model.py +27 -0
- dev/test_data/rdf_shacl/test_main/unexpected/regression_len_constraint_on_class_property/meta_model.py +61 -0
- dev/test_data/real_meta_models/aas_core_meta.v3.py +5721 -0
- dev/test_data/smoke/test_main/unexpected/infer_for_schema_error/meta_model.py +12 -0
- dev/test_data/smoke/test_main/unexpected/intermediate_error/meta_model.py +18 -0
- dev/test_data/smoke/test_main/unexpected/parse_error/meta_model.py +5 -0
- dev/test_data/smoke/test_main/unexpected/pattern_verification_unparsable_regex/direct_match/meta_model.py +8 -0
- dev/test_data/smoke/test_main/unexpected/type_error/meta_model.py +18 -0
- dev/tests/__init__.py +1 -0
- dev/tests/common.py +197 -0
- dev/tests/cpp/__init__.py +0 -0
- dev/tests/cpp/test_common.py +32 -0
- dev/tests/cpp/test_main.py +144 -0
- dev/tests/cpp/test_pattern.py +188 -0
- dev/tests/cpp/test_verification.py +189 -0
- dev/tests/cpp/test_yielding.py +225 -0
- dev/tests/csharp/__init__.py +0 -0
- dev/tests/csharp/live_test_main.py +109 -0
- dev/tests/csharp/test_common.py +28 -0
- dev/tests/csharp/test_description.py +684 -0
- dev/tests/csharp/test_main.py +129 -0
- dev/tests/csharp/test_structure.py +93 -0
- dev/tests/csharp/test_verification.py +82 -0
- dev/tests/description.py +29 -0
- dev/tests/golang/__init__.py +0 -0
- dev/tests/golang/test_common.py +78 -0
- dev/tests/golang/test_main.py +128 -0
- dev/tests/infer_for_schema/__init__.py +0 -0
- dev/tests/infer_for_schema/common.py +47 -0
- dev/tests/infer_for_schema/test_len_on_properties.py +955 -0
- dev/tests/infer_for_schema/test_len_on_self.py +580 -0
- dev/tests/infer_for_schema/test_patterns_on_properties.py +686 -0
- dev/tests/infer_for_schema/test_patterns_on_self.py +258 -0
- dev/tests/infer_for_schema/test_property_in_set_of_enumeration_literals.py +600 -0
- dev/tests/infer_for_schema/test_property_in_set_of_primitives.py +549 -0
- dev/tests/intermediate/__init__.py +0 -0
- dev/tests/intermediate/test_constructor.py +719 -0
- dev/tests/intermediate/test_hierarchy.py +221 -0
- dev/tests/intermediate/test_revm.py +134 -0
- dev/tests/intermediate/test_translate.py +337 -0
- dev/tests/intermediate/test_type_inference.py +333 -0
- dev/tests/intermediate/test_types.py +169 -0
- dev/tests/java/__init__.py +0 -0
- dev/tests/java/test_common.py +20 -0
- dev/tests/java/test_description.py +128 -0
- dev/tests/java/test_main.py +234 -0
- dev/tests/jsonld_context/test_main.py +79 -0
- dev/tests/opcua/__init__.py +3 -0
- dev/tests/opcua/test_main.py +110 -0
- dev/tests/our_jsonschema/__init__.py +3 -0
- dev/tests/our_jsonschema/test_main.py +232 -0
- dev/tests/parse/__init__.py +0 -0
- dev/tests/parse/test_parse.py +503 -0
- dev/tests/parse/test_retree.py +272 -0
- dev/tests/proto/__init__.py +0 -0
- dev/tests/proto/test_main.py +112 -0
- dev/tests/python/__init__.py +0 -0
- dev/tests/python/test_common.py +124 -0
- dev/tests/python/test_main.py +126 -0
- dev/tests/python/test_xml_playground.py +254 -0
- dev/tests/python_protobuf/__init__.py +0 -0
- dev/tests/python_protobuf/test_main.py +111 -0
- dev/tests/rdf_shacl/__init__.py +0 -0
- dev/tests/rdf_shacl/test_common.py +32 -0
- dev/tests/rdf_shacl/test_description.py +223 -0
- dev/tests/rdf_shacl/test_main.py +194 -0
- dev/tests/smoke/__init__.py +0 -0
- dev/tests/smoke/test_main.py +83 -0
- dev/tests/test_common.py +94 -0
- dev/tests/typescript/__init__.py +0 -0
- dev/tests/typescript/test_common.py +108 -0
- dev/tests/typescript/test_main.py +125 -0
- dev/tests/xsd/__init__.py +0 -0
- dev/tests/xsd/test_main.py +227 -0
- dev/tests/yielding/__init__.py +0 -0
- dev/tests/yielding/test_linear.py +558 -0
|
@@ -0,0 +1,1510 @@
|
|
|
1
|
+
"""Generate TypeScript code for JSON-ization based on the intermediate representation."""
|
|
2
|
+
|
|
3
|
+
import io
|
|
4
|
+
import textwrap
|
|
5
|
+
from typing import Tuple, Optional, List
|
|
6
|
+
|
|
7
|
+
from icontract import ensure
|
|
8
|
+
|
|
9
|
+
from aas_core_codegen import intermediate, naming, specific_implementations
|
|
10
|
+
from aas_core_codegen.common import (
|
|
11
|
+
Error,
|
|
12
|
+
Stripped,
|
|
13
|
+
Identifier,
|
|
14
|
+
assert_never,
|
|
15
|
+
indent_but_first_line,
|
|
16
|
+
)
|
|
17
|
+
from aas_core_codegen.typescript import (
|
|
18
|
+
common as typescript_common,
|
|
19
|
+
naming as typescript_naming,
|
|
20
|
+
description as typescript_description,
|
|
21
|
+
)
|
|
22
|
+
from aas_core_codegen.typescript.common import (
|
|
23
|
+
INDENT as I,
|
|
24
|
+
INDENT2 as II,
|
|
25
|
+
INDENT3 as III,
|
|
26
|
+
INDENT4 as IIII,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# region De-serialization
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _generate_bool_from_jsonable() -> Stripped:
|
|
34
|
+
"""Generate the function to decode a ``bool`` from a JSON-able."""
|
|
35
|
+
return Stripped(
|
|
36
|
+
f"""\
|
|
37
|
+
/**
|
|
38
|
+
* Parse `jsonable` as a boolean.
|
|
39
|
+
*
|
|
40
|
+
* @param jsonable - to be parsed
|
|
41
|
+
* @returns parsed boolean value, or an error
|
|
42
|
+
*/
|
|
43
|
+
function booleanFromJsonable(
|
|
44
|
+
{I}jsonable: JsonValue
|
|
45
|
+
): AasCommon.Either<boolean, DeserializationError> {{
|
|
46
|
+
{I}// `typeof` seems to be optimized these days, so we use it instead of
|
|
47
|
+
{I}// literal comparison, see:
|
|
48
|
+
{I}// https://stackoverflow.com/questions/61786250/is-typeof-faster-than-literal-comparison
|
|
49
|
+
|
|
50
|
+
{I}if (jsonable === null) {{
|
|
51
|
+
{II}return newDeserializationError<boolean>(
|
|
52
|
+
{III}"Expected a boolean, but got null"
|
|
53
|
+
{II});
|
|
54
|
+
{I}}}
|
|
55
|
+
{I}if (typeof jsonable !== "boolean") {{
|
|
56
|
+
{II}return newDeserializationError<boolean>(
|
|
57
|
+
{III}`Expected a boolean, but got ${{typeof jsonable}}`
|
|
58
|
+
{II});
|
|
59
|
+
{I}}}
|
|
60
|
+
|
|
61
|
+
{I}return new AasCommon.Either<boolean, DeserializationError>(jsonable, null);
|
|
62
|
+
}}"""
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _generate_int_from_jsonable() -> Stripped:
|
|
67
|
+
"""Generate the function to decode an ``int`` from a JSON-able."""
|
|
68
|
+
return Stripped(
|
|
69
|
+
f"""\
|
|
70
|
+
/**
|
|
71
|
+
* Parse `jsonable` as an integer.
|
|
72
|
+
*
|
|
73
|
+
* @param jsonable - to be parsed
|
|
74
|
+
* @returns parsed integer value, or an error
|
|
75
|
+
*/
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
77
|
+
function integerFromJsonable(
|
|
78
|
+
{I}jsonable: JsonValue
|
|
79
|
+
): AasCommon.Either<number, DeserializationError> {{
|
|
80
|
+
{I}if (jsonable === null) {{
|
|
81
|
+
{II}return newDeserializationError<number>(
|
|
82
|
+
{III}"Expected an integer number, but got null"
|
|
83
|
+
{II});
|
|
84
|
+
{I}}}
|
|
85
|
+
{I}if (typeof jsonable !== "number") {{
|
|
86
|
+
{II}return newDeserializationError<number>(
|
|
87
|
+
{III}`Expected an integer number, but got: ${{typeof jsonable}}`
|
|
88
|
+
{II});
|
|
89
|
+
{I}}}
|
|
90
|
+
|
|
91
|
+
{I}if (!Number.isInteger(jsonable)) {{
|
|
92
|
+
{II}return newDeserializationError<number>(
|
|
93
|
+
{III}`Expected an integer number, but got: ${{jsonable}}`
|
|
94
|
+
{II});
|
|
95
|
+
{I}}}
|
|
96
|
+
|
|
97
|
+
{I}return new AasCommon.Either<number, DeserializationError>(jsonable, null);
|
|
98
|
+
}}"""
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _generate_float_from_jsonable() -> Stripped:
|
|
103
|
+
"""Generate the function to decode a ``float`` from a JSON-able."""
|
|
104
|
+
return Stripped(
|
|
105
|
+
f"""\
|
|
106
|
+
/**
|
|
107
|
+
* Parse `jsonable` as a number.
|
|
108
|
+
*
|
|
109
|
+
* @param jsonable - to be parsed
|
|
110
|
+
* @returns parsed numeric value, or an error
|
|
111
|
+
*/
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
113
|
+
function numberFromJsonable(
|
|
114
|
+
{I}jsonable: JsonValue
|
|
115
|
+
): AasCommon.Either<number, DeserializationError> {{
|
|
116
|
+
{I}if (jsonable === null) {{
|
|
117
|
+
{II}return newDeserializationError<number>(
|
|
118
|
+
{III}"Expected a number, but got null"
|
|
119
|
+
{II});
|
|
120
|
+
{I}}}
|
|
121
|
+
{I}if (typeof jsonable !== "number") {{
|
|
122
|
+
{II}return newDeserializationError<number>(
|
|
123
|
+
{III}`Expected a number, but got: ${{typeof jsonable}}`
|
|
124
|
+
{II});
|
|
125
|
+
{I}}}
|
|
126
|
+
|
|
127
|
+
{I}return new AasCommon.Either<number, DeserializationError>(jsonable, null);
|
|
128
|
+
}}"""
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _generate_str_from_jsonable() -> Stripped:
|
|
133
|
+
"""Generate the function to decode a ``str`` from a JSON-able."""
|
|
134
|
+
return Stripped(
|
|
135
|
+
f"""\
|
|
136
|
+
/**
|
|
137
|
+
* Parse `jsonable` as a string.
|
|
138
|
+
*
|
|
139
|
+
* @param jsonable - to be parsed
|
|
140
|
+
* @returns parsed string value, or an error
|
|
141
|
+
*/
|
|
142
|
+
function stringFromJsonable(
|
|
143
|
+
{I}jsonable: JsonValue
|
|
144
|
+
): AasCommon.Either<string, DeserializationError> {{
|
|
145
|
+
{I}if (jsonable === null) {{
|
|
146
|
+
{II}return newDeserializationError<string>(
|
|
147
|
+
{III}"Expected a string, but got null"
|
|
148
|
+
{II});
|
|
149
|
+
{I}}}
|
|
150
|
+
{I}if (typeof jsonable !== "string") {{
|
|
151
|
+
{II}return newDeserializationError<string>(
|
|
152
|
+
{III}`Expected a string, but got: ${{typeof jsonable}}`
|
|
153
|
+
{II});
|
|
154
|
+
{I}}}
|
|
155
|
+
|
|
156
|
+
{I}return new AasCommon.Either<string, DeserializationError>(jsonable, null);
|
|
157
|
+
}}"""
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _generate_bytes_from_jsonable() -> Stripped:
|
|
162
|
+
"""Generate the function to decode ``bytes`` from a JSON-able."""
|
|
163
|
+
return Stripped(
|
|
164
|
+
f"""\
|
|
165
|
+
/**
|
|
166
|
+
* Parse `jsonable` as a byte array.
|
|
167
|
+
*
|
|
168
|
+
* @param jsonable - to be parsed
|
|
169
|
+
* @returns parsed byte array, or an error
|
|
170
|
+
*/
|
|
171
|
+
function bytesFromJsonable(
|
|
172
|
+
{I}jsonable: JsonValue
|
|
173
|
+
): AasCommon.Either<Uint8Array, DeserializationError> {{
|
|
174
|
+
{I}if (jsonable === null) {{
|
|
175
|
+
{II}return newDeserializationError<Uint8Array>(
|
|
176
|
+
{III}"Expected a base64-encoded string, but got null"
|
|
177
|
+
{II});
|
|
178
|
+
{I}}}
|
|
179
|
+
{I}if (typeof jsonable !== "string") {{
|
|
180
|
+
{II}return newDeserializationError<Uint8Array>(
|
|
181
|
+
{III}`Expected a base64-encoded string, but got: ${{typeof jsonable}}`
|
|
182
|
+
{II});
|
|
183
|
+
{I}}}
|
|
184
|
+
|
|
185
|
+
{I}const either = AasCommon.base64Decode(jsonable);
|
|
186
|
+
{I}if (either.error !== null) {{
|
|
187
|
+
{II}return newDeserializationError<Uint8Array>(either.error);
|
|
188
|
+
{I}}}
|
|
189
|
+
{I}return new AasCommon.Either<Uint8Array, DeserializationError>(
|
|
190
|
+
{II}either.mustValue(), null
|
|
191
|
+
{I});
|
|
192
|
+
}}"""
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _generate_enumeration_from_jsonable(
|
|
197
|
+
enumeration: intermediate.Enumeration,
|
|
198
|
+
) -> Stripped:
|
|
199
|
+
"""Generate the deserialization method for an enumeration."""
|
|
200
|
+
enum_name = typescript_naming.enum_name(identifier=enumeration.name)
|
|
201
|
+
|
|
202
|
+
function_name = typescript_naming.function_name(
|
|
203
|
+
Identifier(f"{enumeration.name}_from_jsonable")
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
enum_from_str = typescript_naming.function_name(
|
|
207
|
+
Identifier(f"{enumeration.name}_from_string")
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
return Stripped(
|
|
211
|
+
f"""\
|
|
212
|
+
/**
|
|
213
|
+
* Parse `jsonable` structure as a literal
|
|
214
|
+
* of {{@link {typescript_common.TYPES_MODULE}!{enum_name}}}.
|
|
215
|
+
*
|
|
216
|
+
* @param jsonable - to be parsed
|
|
217
|
+
* @returns parsed literal, or an error if `jsonable` invalid
|
|
218
|
+
*/
|
|
219
|
+
export function {function_name}(
|
|
220
|
+
{I}jsonable: JsonValue
|
|
221
|
+
): AasCommon.Either<AasTypes.{enum_name}, DeserializationError> {{
|
|
222
|
+
{I}if (typeof jsonable !== "string") {{
|
|
223
|
+
{II}return newDeserializationError<AasTypes.{enum_name}>(
|
|
224
|
+
{III}`Expected a string, but got: ${{typeof jsonable}}`
|
|
225
|
+
{II});
|
|
226
|
+
{I}}}
|
|
227
|
+
|
|
228
|
+
{I}const literal = AasStringification.{enum_from_str}(jsonable);
|
|
229
|
+
{I}if (literal === null) {{
|
|
230
|
+
{II}return newDeserializationError<AasTypes.{enum_name}>(
|
|
231
|
+
{III}"Not a valid string representation of " +
|
|
232
|
+
{IIII}`a literal of {enum_name}: ${{jsonable}}`
|
|
233
|
+
{II});
|
|
234
|
+
{I}}}
|
|
235
|
+
|
|
236
|
+
{I}return new AasCommon.Either<
|
|
237
|
+
{II}AasTypes.{enum_name},
|
|
238
|
+
{II}DeserializationError
|
|
239
|
+
{I}>(literal, null);
|
|
240
|
+
}}"""
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _generate_dispatch_map_for_interface(
|
|
245
|
+
interface: intermediate.Interface,
|
|
246
|
+
) -> Stripped:
|
|
247
|
+
"""Generate a mapping model type 🠒 de-serialization function."""
|
|
248
|
+
assert len(interface.base.concrete_descendants) > 0, (
|
|
249
|
+
"Expected a class to have concrete descendants. "
|
|
250
|
+
"Otherwise we do not know how to de-serialize it."
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
mapping_name = typescript_naming.constant_name(
|
|
254
|
+
Identifier(f"{interface.name}_from_jsonable_dispatch")
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
interface_name = typescript_naming.interface_name(interface.name)
|
|
258
|
+
|
|
259
|
+
mapping_writer = io.StringIO()
|
|
260
|
+
mapping_writer.write(
|
|
261
|
+
f"""\
|
|
262
|
+
const {mapping_name} =
|
|
263
|
+
{I}new Map<
|
|
264
|
+
{II}string,
|
|
265
|
+
{II}(JsonValue) => AasCommon.Either<
|
|
266
|
+
{III}AasTypes.{interface_name},
|
|
267
|
+
{III}DeserializationError
|
|
268
|
+
{II}>
|
|
269
|
+
{I}>(
|
|
270
|
+
{II}[
|
|
271
|
+
"""
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
for i, implementer in enumerate(interface.implementers):
|
|
275
|
+
if len(implementer.concrete_descendants) == 0:
|
|
276
|
+
function_name_for_implementer = typescript_naming.function_name(
|
|
277
|
+
Identifier(f"{implementer.name}_from_jsonable")
|
|
278
|
+
)
|
|
279
|
+
else:
|
|
280
|
+
# NOTE (mristin, 2022-11-25):
|
|
281
|
+
# We can not use the public function as it would end in an endless dispatch
|
|
282
|
+
# loop. Hence, we introduce a function which assumes the type and explicitly
|
|
283
|
+
# does not dispatch.
|
|
284
|
+
function_name_for_implementer = typescript_naming.function_name(
|
|
285
|
+
Identifier(f"{implementer.name}_from_jsonable_without_dispatch")
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
implementer_literal = typescript_common.string_literal(
|
|
289
|
+
naming.json_model_type(implementer.name)
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
mapping_writer.write(
|
|
293
|
+
f"""\
|
|
294
|
+
{III}[
|
|
295
|
+
{IIII}{implementer_literal},
|
|
296
|
+
{IIII}{function_name_for_implementer}
|
|
297
|
+
{III}]"""
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
if i < len(interface.implementers) - 1:
|
|
301
|
+
mapping_writer.write(",\n")
|
|
302
|
+
else:
|
|
303
|
+
mapping_writer.write("\n")
|
|
304
|
+
|
|
305
|
+
mapping_writer.write(
|
|
306
|
+
f"""\
|
|
307
|
+
{II}]
|
|
308
|
+
{I});"""
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
return Stripped(mapping_writer.getvalue())
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def _generate_dispatch_from_jsonable(interface: intermediate.Interface) -> Stripped:
|
|
315
|
+
"""Generate the de-serialization dispatch for an abstract class."""
|
|
316
|
+
function_name = typescript_naming.function_name(
|
|
317
|
+
Identifier(f"{interface.name}_from_jsonable")
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
interface_name = typescript_naming.interface_name(interface.name)
|
|
321
|
+
|
|
322
|
+
mapping_name = typescript_naming.constant_name(
|
|
323
|
+
Identifier(f"{interface.name}_from_jsonable_dispatch")
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
return Stripped(
|
|
327
|
+
f"""\
|
|
328
|
+
/**
|
|
329
|
+
* Parse `jsonable` as an instance
|
|
330
|
+
* of {{@link {typescript_common.TYPES_MODULE}!{interface_name}}}.
|
|
331
|
+
*
|
|
332
|
+
* @param jsonable - to be parsed
|
|
333
|
+
* @returns parsed instance, or error if `jsonable` is invalid
|
|
334
|
+
*/
|
|
335
|
+
export function {function_name}(
|
|
336
|
+
{I}jsonable: JsonValue
|
|
337
|
+
): AasCommon.Either<
|
|
338
|
+
{I}AasTypes.{interface_name},
|
|
339
|
+
{I}DeserializationError
|
|
340
|
+
> {{
|
|
341
|
+
{I}if (jsonable === null) {{
|
|
342
|
+
{II}return newDeserializationError<AasTypes.{interface_name}>(
|
|
343
|
+
{III}"Expected a JSON object, but got null"
|
|
344
|
+
{II});
|
|
345
|
+
{I}}}
|
|
346
|
+
{I}if (Array.isArray(jsonable)) {{
|
|
347
|
+
{II}return newDeserializationError<AasTypes.{interface_name}>(
|
|
348
|
+
{III}"Expected a JSON object, but got a JSON array"
|
|
349
|
+
{II});
|
|
350
|
+
{I}}}
|
|
351
|
+
{I}if (typeof jsonable !== "object") {{
|
|
352
|
+
{II}return newDeserializationError<AasTypes.{interface_name}>(
|
|
353
|
+
{III}`Expected a JSON object, but got: ${{typeof jsonable}}`
|
|
354
|
+
{II});
|
|
355
|
+
{I}}}
|
|
356
|
+
|
|
357
|
+
{I}const modelType = jsonable["modelType"];
|
|
358
|
+
{I}if (modelType === undefined) {{
|
|
359
|
+
{II}return newDeserializationError<AasTypes.{interface_name}>(
|
|
360
|
+
{III}"The required property modelType is missing"
|
|
361
|
+
{II});
|
|
362
|
+
{I}}}
|
|
363
|
+
|
|
364
|
+
{I}if (typeof modelType !== "string") {{
|
|
365
|
+
{II}return newDeserializationError<AasTypes.{interface_name}>(
|
|
366
|
+
{III}`Expected the property modelType to be a string, but got: ${{typeof modelType}}`
|
|
367
|
+
{II});
|
|
368
|
+
{I}}}
|
|
369
|
+
|
|
370
|
+
{I}const dispatch = {mapping_name}.get(modelType);
|
|
371
|
+
{I}if (dispatch === undefined) {{
|
|
372
|
+
{II}return newDeserializationError<AasTypes.{interface_name}>(
|
|
373
|
+
{III}`Unexpected model type for {interface_name}: ${{modelType}}`
|
|
374
|
+
{II});
|
|
375
|
+
{I}}}
|
|
376
|
+
|
|
377
|
+
{I}return dispatch(jsonable);
|
|
378
|
+
}}"""
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
_PARSE_FUNCTION_BY_PRIMITIVE_TYPE = {
|
|
383
|
+
intermediate.PrimitiveType.BOOL: "booleanFromJsonable",
|
|
384
|
+
intermediate.PrimitiveType.INT: "integerFromJsonable",
|
|
385
|
+
intermediate.PrimitiveType.FLOAT: "numberFromJsonable",
|
|
386
|
+
intermediate.PrimitiveType.STR: "stringFromJsonable",
|
|
387
|
+
intermediate.PrimitiveType.BYTEARRAY: "bytesFromJsonable",
|
|
388
|
+
}
|
|
389
|
+
assert all(
|
|
390
|
+
literal in _PARSE_FUNCTION_BY_PRIMITIVE_TYPE
|
|
391
|
+
for literal in intermediate.PrimitiveType
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def _parse_function_for_atomic_value(
|
|
396
|
+
type_annotation: intermediate.AtomicTypeAnnotation,
|
|
397
|
+
) -> Stripped:
|
|
398
|
+
"""Determine the parse function for deserializing an atomic non-optional value."""
|
|
399
|
+
function_name: str
|
|
400
|
+
|
|
401
|
+
if isinstance(type_annotation, intermediate.PrimitiveTypeAnnotation):
|
|
402
|
+
function_name = _PARSE_FUNCTION_BY_PRIMITIVE_TYPE[type_annotation.a_type]
|
|
403
|
+
|
|
404
|
+
elif isinstance(type_annotation, intermediate.OurTypeAnnotation):
|
|
405
|
+
our_type = type_annotation.our_type
|
|
406
|
+
|
|
407
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
408
|
+
function_name = typescript_naming.function_name(
|
|
409
|
+
Identifier(f"{our_type.name}_from_jsonable")
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
elif isinstance(
|
|
413
|
+
our_type,
|
|
414
|
+
(
|
|
415
|
+
intermediate.AbstractClass,
|
|
416
|
+
intermediate.ConcreteClass,
|
|
417
|
+
),
|
|
418
|
+
):
|
|
419
|
+
if our_type.interface is not None:
|
|
420
|
+
assert our_type.interface.name == our_type.name, (
|
|
421
|
+
"Assume that the interface name and the class name in "
|
|
422
|
+
"the intermediate representation are the same, so that the "
|
|
423
|
+
"``*_from_jsonable`` name makes sense in all cases"
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
function_name = typescript_naming.function_name(
|
|
427
|
+
Identifier(f"{our_type.name}_from_jsonable")
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
431
|
+
function_name = _PARSE_FUNCTION_BY_PRIMITIVE_TYPE[our_type.constrainee]
|
|
432
|
+
|
|
433
|
+
else:
|
|
434
|
+
assert_never(our_type)
|
|
435
|
+
else:
|
|
436
|
+
assert_never(type_annotation)
|
|
437
|
+
|
|
438
|
+
return Stripped(function_name)
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
def _generate_setter(cls: intermediate.ConcreteClass) -> Stripped:
|
|
442
|
+
"""Generate a class which allows us to dispatch de-serialization for properties."""
|
|
443
|
+
blocks = [] # type: List[Stripped]
|
|
444
|
+
|
|
445
|
+
for i, prop in enumerate(cls.properties):
|
|
446
|
+
prop_name = typescript_naming.property_name(prop.name)
|
|
447
|
+
prop_type = typescript_common.generate_type(
|
|
448
|
+
prop.type_annotation, types_module=Identifier("AasTypes")
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
# NOTE (mristin, 2022-11-25):
|
|
452
|
+
# We make all the properties optional since we switch over the properties
|
|
453
|
+
# during the de-serialization.
|
|
454
|
+
if not isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation):
|
|
455
|
+
prop_type = Stripped(f"{prop_type} | null")
|
|
456
|
+
|
|
457
|
+
blocks.append(Stripped(f"{prop_name}: {prop_type} = null;"))
|
|
458
|
+
|
|
459
|
+
if cls.serialization.with_model_type:
|
|
460
|
+
# NOTE (mristin):
|
|
461
|
+
# If the serialization requires a model type, we consequently parse and set it
|
|
462
|
+
# in the setter. The model type thus obtained is *not* used for any dispatch. We
|
|
463
|
+
# only use this value for verification to make sure that the model type
|
|
464
|
+
# of the instances is consistent with the expected value for its concrete
|
|
465
|
+
# class. This will be performed even though the code might have had to parse
|
|
466
|
+
# model type before for the dispatch. We decided to double-check to cover the
|
|
467
|
+
# case where a dispatch is *unnecessary* (*e.g.*, the caller knows the expected
|
|
468
|
+
# runtime type), but the model type might still be invalid in the input. Hence,
|
|
469
|
+
# when the dispatch is *necessary*, the model type JSON property will be parsed
|
|
470
|
+
# twice, which is a cost we currently find acceptable.
|
|
471
|
+
prop_name = typescript_naming.property_name(Identifier("model_type"))
|
|
472
|
+
blocks.append(
|
|
473
|
+
Stripped(
|
|
474
|
+
f"""\
|
|
475
|
+
// Used only for verification, not for dispatch!
|
|
476
|
+
{prop_name}: string | null = null;"""
|
|
477
|
+
)
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
for i, prop in enumerate(cls.properties):
|
|
481
|
+
prop_name = typescript_naming.property_name(prop.name)
|
|
482
|
+
|
|
483
|
+
type_anno = intermediate.beneath_optional(prop.type_annotation)
|
|
484
|
+
if isinstance(
|
|
485
|
+
type_anno,
|
|
486
|
+
(intermediate.PrimitiveTypeAnnotation, intermediate.OurTypeAnnotation),
|
|
487
|
+
):
|
|
488
|
+
function_name = _parse_function_for_atomic_value(type_anno)
|
|
489
|
+
body = Stripped(
|
|
490
|
+
f"""\
|
|
491
|
+
const parsedOrError = {function_name}(
|
|
492
|
+
{I}jsonable
|
|
493
|
+
);
|
|
494
|
+
if (parsedOrError.error !== null) {{
|
|
495
|
+
{I}return parsedOrError.error;
|
|
496
|
+
}} else {{
|
|
497
|
+
{I}this.{prop_name} = parsedOrError.mustValue();
|
|
498
|
+
{I}return null;
|
|
499
|
+
}}"""
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
elif isinstance(type_anno, intermediate.ListTypeAnnotation):
|
|
503
|
+
assert not isinstance(
|
|
504
|
+
type_anno.items,
|
|
505
|
+
(intermediate.OptionalTypeAnnotation, intermediate.ListTypeAnnotation),
|
|
506
|
+
), (
|
|
507
|
+
"We chose to implement only a very limited pattern matching; "
|
|
508
|
+
"see intermediate._translate_._verify_only_simple_type_patterns"
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
items_type = typescript_common.generate_type(
|
|
512
|
+
type_anno.items, types_module=Identifier("AasTypes")
|
|
513
|
+
)
|
|
514
|
+
parse_function = _parse_function_for_atomic_value(type_anno.items)
|
|
515
|
+
|
|
516
|
+
body = Stripped(
|
|
517
|
+
f"""\
|
|
518
|
+
if (jsonable === null) {{
|
|
519
|
+
{I}return new DeserializationError(
|
|
520
|
+
{II}"Expected an iterable, but got null"
|
|
521
|
+
{I});
|
|
522
|
+
}}
|
|
523
|
+
if (typeof jsonable !== "object") {{
|
|
524
|
+
{I}return new DeserializationError(
|
|
525
|
+
{II}`Expected an iterable, but got: ${{typeof jsonable}}`
|
|
526
|
+
{I});
|
|
527
|
+
}}
|
|
528
|
+
if (typeof jsonable[Symbol.iterator] !== "function") {{
|
|
529
|
+
{I}return new DeserializationError(
|
|
530
|
+
{II}"Expected an iterable with iterator function, " +
|
|
531
|
+
{III}`but got iterator of type: ${{typeof jsonable[Symbol.iterator]}}`
|
|
532
|
+
{I});
|
|
533
|
+
}}
|
|
534
|
+
|
|
535
|
+
const iterable = <Iterable<JsonValue>>jsonable;
|
|
536
|
+
|
|
537
|
+
const items =
|
|
538
|
+
{I}new Array<{items_type}>();
|
|
539
|
+
|
|
540
|
+
let i = 0;
|
|
541
|
+
for (const jsonableItem of iterable) {{
|
|
542
|
+
{I}const itemOrError = {parse_function}(
|
|
543
|
+
{II}jsonableItem
|
|
544
|
+
{I});
|
|
545
|
+
|
|
546
|
+
{I}if (itemOrError.error !== null) {{
|
|
547
|
+
{II}itemOrError.error.path.prepend(
|
|
548
|
+
{III}new IndexSegment(
|
|
549
|
+
{IIII}iterable,
|
|
550
|
+
{IIII}i
|
|
551
|
+
{III})
|
|
552
|
+
{II});
|
|
553
|
+
{II}return itemOrError.error;
|
|
554
|
+
{I}}}
|
|
555
|
+
|
|
556
|
+
{I}items.push(itemOrError.mustValue());
|
|
557
|
+
{I}i++;
|
|
558
|
+
}}
|
|
559
|
+
|
|
560
|
+
this.{prop_name} = items;
|
|
561
|
+
return null;"""
|
|
562
|
+
)
|
|
563
|
+
|
|
564
|
+
else:
|
|
565
|
+
assert_never(type_anno)
|
|
566
|
+
|
|
567
|
+
method_name = typescript_naming.method_name(
|
|
568
|
+
Identifier(f"set_{prop.name}_from_jsonable")
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
method_writer = io.StringIO()
|
|
572
|
+
method_writer.write(
|
|
573
|
+
f"""\
|
|
574
|
+
/**
|
|
575
|
+
* Parse `jsonable` as the value of {{@link {prop_name}}}.
|
|
576
|
+
*
|
|
577
|
+
* @param jsonable - to be parsed
|
|
578
|
+
* @returns error, if any
|
|
579
|
+
*/
|
|
580
|
+
{method_name}(
|
|
581
|
+
{I}jsonable: JsonValue
|
|
582
|
+
): DeserializationError | null {{
|
|
583
|
+
{I}{indent_but_first_line(body, I)}
|
|
584
|
+
}}"""
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
blocks.append(Stripped(method_writer.getvalue()))
|
|
588
|
+
|
|
589
|
+
if cls.serialization.with_model_type:
|
|
590
|
+
method_name = typescript_naming.method_name(
|
|
591
|
+
Identifier("set_model_type_from_jsonable")
|
|
592
|
+
)
|
|
593
|
+
prop_name = typescript_naming.property_name(Identifier("model_type"))
|
|
594
|
+
|
|
595
|
+
blocks.append(
|
|
596
|
+
Stripped(
|
|
597
|
+
f"""\
|
|
598
|
+
/**
|
|
599
|
+
* Parse `jsonable` as the model type of the concrete instance.
|
|
600
|
+
*
|
|
601
|
+
* This is intended only for verification, and no dispatch is performed.
|
|
602
|
+
*
|
|
603
|
+
* @param jsonable - to be parsed
|
|
604
|
+
* @returns error, if any
|
|
605
|
+
*/
|
|
606
|
+
{method_name}(
|
|
607
|
+
{I}jsonable: JsonValue
|
|
608
|
+
): DeserializationError | null {{
|
|
609
|
+
{I}const parsedOrError = stringFromJsonable(
|
|
610
|
+
{II}jsonable
|
|
611
|
+
{I});
|
|
612
|
+
{I}if (parsedOrError.error !== null) {{
|
|
613
|
+
{II}return parsedOrError.error;
|
|
614
|
+
{I}}} else {{
|
|
615
|
+
{II}this.{prop_name} = parsedOrError.mustValue();
|
|
616
|
+
{II}return null;
|
|
617
|
+
{I}}}
|
|
618
|
+
}}"""
|
|
619
|
+
)
|
|
620
|
+
)
|
|
621
|
+
|
|
622
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
623
|
+
setter_cls_name = typescript_naming.class_name(Identifier(f"Setter_for_{cls.name}"))
|
|
624
|
+
|
|
625
|
+
writer = io.StringIO()
|
|
626
|
+
writer.write(
|
|
627
|
+
f"""\
|
|
628
|
+
/**
|
|
629
|
+
* Provide de-serialize & set methods for properties
|
|
630
|
+
* of {{@link {typescript_common.TYPES_MODULE}!{cls_name}}}.
|
|
631
|
+
*/
|
|
632
|
+
class {setter_cls_name} {{
|
|
633
|
+
"""
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
for i, block in enumerate(blocks):
|
|
637
|
+
if i > 0:
|
|
638
|
+
writer.write("\n\n")
|
|
639
|
+
|
|
640
|
+
writer.write(textwrap.indent(block, I))
|
|
641
|
+
|
|
642
|
+
writer.write("\n}")
|
|
643
|
+
|
|
644
|
+
return Stripped(writer.getvalue())
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
def _generate_setter_map(cls: intermediate.ConcreteClass) -> Stripped:
|
|
648
|
+
"""Generate a map ``JSON property name`` -> deserialization on a setter."""
|
|
649
|
+
# fmt: off
|
|
650
|
+
assert (
|
|
651
|
+
sorted(
|
|
652
|
+
(arg.name, str(arg.type_annotation))
|
|
653
|
+
for arg in cls.constructor.arguments
|
|
654
|
+
) == sorted(
|
|
655
|
+
(prop.name, str(prop.type_annotation))
|
|
656
|
+
for prop in cls.properties
|
|
657
|
+
)
|
|
658
|
+
), (
|
|
659
|
+
"(mristin, 2022-11-25) We assume that the properties and constructor arguments "
|
|
660
|
+
"are identical at this point. If this is not the case, we have to re-write the "
|
|
661
|
+
"logic substantially! Please contact the developers if you see this."
|
|
662
|
+
)
|
|
663
|
+
# fmt: on
|
|
664
|
+
|
|
665
|
+
identifiers_expressions = [] # type: List[Tuple[Identifier, Stripped]]
|
|
666
|
+
|
|
667
|
+
setter_cls_name = typescript_naming.class_name(Identifier(f"Setter_for_{cls.name}"))
|
|
668
|
+
|
|
669
|
+
for prop in cls.properties:
|
|
670
|
+
json_identifier = naming.json_property(prop.name)
|
|
671
|
+
method_name = typescript_naming.method_name(
|
|
672
|
+
Identifier(f"set_{prop.name}_from_jsonable")
|
|
673
|
+
)
|
|
674
|
+
|
|
675
|
+
identifiers_expressions.append(
|
|
676
|
+
(json_identifier, Stripped(f"{setter_cls_name}.prototype.{method_name}"))
|
|
677
|
+
)
|
|
678
|
+
|
|
679
|
+
map_name = typescript_naming.constant_name(Identifier(f"setter_map_for_{cls.name}"))
|
|
680
|
+
|
|
681
|
+
writer = io.StringIO()
|
|
682
|
+
writer.write(
|
|
683
|
+
f"""\
|
|
684
|
+
const {map_name} =
|
|
685
|
+
{I}new Map<
|
|
686
|
+
{II}string,
|
|
687
|
+
{II}(
|
|
688
|
+
{III}jsonable: JsonValue
|
|
689
|
+
{II}) => DeserializationError | null
|
|
690
|
+
{I}>(
|
|
691
|
+
{II}[
|
|
692
|
+
"""
|
|
693
|
+
)
|
|
694
|
+
|
|
695
|
+
for identifier, expression in identifiers_expressions:
|
|
696
|
+
writer.write(
|
|
697
|
+
f"""\
|
|
698
|
+
{III}[
|
|
699
|
+
{IIII}{typescript_common.string_literal(identifier)},
|
|
700
|
+
{IIII}{indent_but_first_line(expression, IIII)}
|
|
701
|
+
{III}],
|
|
702
|
+
"""
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
if cls.serialization.with_model_type:
|
|
706
|
+
# NOTE (mristin):
|
|
707
|
+
# If the serialization requires a model type, we consequently parse and set it
|
|
708
|
+
# in the setter. The model type thus obtained is *not* used for any dispatch. We
|
|
709
|
+
# only use this value for verification to make sure that the model type
|
|
710
|
+
# of the instances is consistent with the expected value for its concrete
|
|
711
|
+
# class. This will be performed even though the code might have had to parse
|
|
712
|
+
# model type before for the dispatch. We decided to double-check to cover the
|
|
713
|
+
# case where a dispatch is *unnecessary* (*e.g.*, the caller knows the expected
|
|
714
|
+
# runtime type), but the model type might still be invalid in the input. Hence,
|
|
715
|
+
# when the dispatch is *necessary*, the model type JSON property will be parsed
|
|
716
|
+
# twice, which is a cost we currently find acceptable.
|
|
717
|
+
json_identifier = naming.json_property(Identifier("model_type"))
|
|
718
|
+
method_name = typescript_naming.method_name(
|
|
719
|
+
Identifier("set_model_type_from_jsonable")
|
|
720
|
+
)
|
|
721
|
+
expression = Stripped(f"{setter_cls_name}.prototype.{method_name}")
|
|
722
|
+
|
|
723
|
+
writer.write(
|
|
724
|
+
f"""\
|
|
725
|
+
{III}[
|
|
726
|
+
{IIII}// The model type here is used only for verification, not for dispatch.
|
|
727
|
+
{IIII}{typescript_common.string_literal(json_identifier)},
|
|
728
|
+
{IIII}{indent_but_first_line(expression, IIII)}
|
|
729
|
+
{III}],
|
|
730
|
+
"""
|
|
731
|
+
)
|
|
732
|
+
|
|
733
|
+
writer.write(
|
|
734
|
+
f"""\
|
|
735
|
+
{II}]
|
|
736
|
+
{I});"""
|
|
737
|
+
)
|
|
738
|
+
|
|
739
|
+
return Stripped(writer.getvalue())
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
def _generate_concrete_class_from_jsonable(
|
|
743
|
+
cls: intermediate.ConcreteClass,
|
|
744
|
+
) -> Stripped:
|
|
745
|
+
"""
|
|
746
|
+
Generate the deserialization function for a concrete class.
|
|
747
|
+
|
|
748
|
+
This function performs no dispatch. If it de-serializes a concrete class with
|
|
749
|
+
concrete descendants, we have to provide a different name. Otherwise, it would
|
|
750
|
+
shadow the name for the dispatch function.
|
|
751
|
+
"""
|
|
752
|
+
# fmt: off
|
|
753
|
+
assert (
|
|
754
|
+
sorted(
|
|
755
|
+
(arg.name, str(arg.type_annotation))
|
|
756
|
+
for arg in cls.constructor.arguments
|
|
757
|
+
) == sorted(
|
|
758
|
+
(prop.name, str(prop.type_annotation))
|
|
759
|
+
for prop in cls.properties
|
|
760
|
+
)
|
|
761
|
+
), (
|
|
762
|
+
"(mristin, 2022-11-30) We assume that the properties and constructor arguments "
|
|
763
|
+
"are identical at this point. If this is not the case, we have to re-write the "
|
|
764
|
+
"logic substantially! Please contact the developers if you see this."
|
|
765
|
+
)
|
|
766
|
+
# fmt: on
|
|
767
|
+
|
|
768
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
769
|
+
|
|
770
|
+
setter_cls_name = typescript_naming.class_name(Identifier(f"Setter_for_{cls.name}"))
|
|
771
|
+
|
|
772
|
+
blocks = [
|
|
773
|
+
Stripped(
|
|
774
|
+
f"""\
|
|
775
|
+
if (jsonable === null) {{
|
|
776
|
+
{I}return newDeserializationError<AasTypes.{cls_name}>(
|
|
777
|
+
{II}"Expected a JSON object, but got null"
|
|
778
|
+
{I});
|
|
779
|
+
}}
|
|
780
|
+
{I}if (Array.isArray(jsonable)) {{
|
|
781
|
+
{II}return newDeserializationError<AasTypes.{cls_name}>(
|
|
782
|
+
{III}"Expected a JSON object, but got a JSON array"
|
|
783
|
+
{II});
|
|
784
|
+
{I}}}
|
|
785
|
+
if (typeof jsonable !== "object") {{
|
|
786
|
+
{I}return newDeserializationError<AasTypes.{cls_name}>(
|
|
787
|
+
{II}`Expected a JSON object, but got: ${{typeof jsonable}}`
|
|
788
|
+
{I});
|
|
789
|
+
}}"""
|
|
790
|
+
),
|
|
791
|
+
Stripped(f"const setter = new {setter_cls_name}();"),
|
|
792
|
+
] # type: List[Stripped]
|
|
793
|
+
|
|
794
|
+
# region Switch on property name
|
|
795
|
+
|
|
796
|
+
map_name = typescript_naming.constant_name(Identifier(f"setter_map_for_{cls.name}"))
|
|
797
|
+
|
|
798
|
+
blocks.append(
|
|
799
|
+
Stripped(
|
|
800
|
+
f"""\
|
|
801
|
+
for (const key in jsonable) {{
|
|
802
|
+
{I}const jsonableValue = jsonable[key];
|
|
803
|
+
{I}const setterMethod =
|
|
804
|
+
{II}{map_name}.get(key);
|
|
805
|
+
|
|
806
|
+
{I}// NOTE (mristin, 2022-11-30):
|
|
807
|
+
{I}// Since we conflate here a JavaScript object with a JSON object, we ignore
|
|
808
|
+
{I}// properties which we do not know how to de-serialize and assume they are
|
|
809
|
+
{I}// related to the *JavaScript* properties of the object or `Object` prototype.
|
|
810
|
+
{I}if (setterMethod === undefined) {{
|
|
811
|
+
{II}continue;
|
|
812
|
+
{I}}}
|
|
813
|
+
|
|
814
|
+
{I}const error = setterMethod.call(setter, jsonableValue);
|
|
815
|
+
{I}if (error !== null) {{
|
|
816
|
+
{II}error.path.prepend(
|
|
817
|
+
{III}new PropertySegment(<JsonObject>jsonable, key)
|
|
818
|
+
{II});
|
|
819
|
+
{II}return new AasCommon.Either<
|
|
820
|
+
{III}AasTypes.{cls_name},
|
|
821
|
+
{III}DeserializationError
|
|
822
|
+
{II}>(
|
|
823
|
+
{IIII}null,
|
|
824
|
+
{IIII}error
|
|
825
|
+
{III});
|
|
826
|
+
{I}}}
|
|
827
|
+
}}"""
|
|
828
|
+
)
|
|
829
|
+
)
|
|
830
|
+
|
|
831
|
+
# region Check required properties
|
|
832
|
+
|
|
833
|
+
required_checks = [] # type: List[Stripped]
|
|
834
|
+
for i, prop in enumerate(cls.properties):
|
|
835
|
+
if isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation):
|
|
836
|
+
continue
|
|
837
|
+
|
|
838
|
+
prop_name = typescript_naming.property_name(prop.name)
|
|
839
|
+
|
|
840
|
+
message_literal = typescript_common.string_literal(
|
|
841
|
+
f"The required property {naming.json_property(prop.name)!r} is missing"
|
|
842
|
+
)
|
|
843
|
+
required_checks.append(
|
|
844
|
+
Stripped(
|
|
845
|
+
f"""\
|
|
846
|
+
if (setter.{prop_name} === null) {{
|
|
847
|
+
{I}return newDeserializationError<
|
|
848
|
+
{II}AasTypes.{cls_name}
|
|
849
|
+
{I}>(
|
|
850
|
+
{II}{message_literal}
|
|
851
|
+
{I});
|
|
852
|
+
}}"""
|
|
853
|
+
)
|
|
854
|
+
)
|
|
855
|
+
|
|
856
|
+
if len(required_checks) > 0:
|
|
857
|
+
blocks.append(Stripped("\n\n".join(required_checks)))
|
|
858
|
+
|
|
859
|
+
# endregion
|
|
860
|
+
|
|
861
|
+
if cls.serialization.with_model_type:
|
|
862
|
+
model_type = naming.json_model_type(cls.name)
|
|
863
|
+
prop_name = typescript_naming.property_name(Identifier("model_type"))
|
|
864
|
+
|
|
865
|
+
blocks.append(
|
|
866
|
+
Stripped(
|
|
867
|
+
f"""\
|
|
868
|
+
if (setter.{prop_name} === null) {{
|
|
869
|
+
{I}return newDeserializationError<
|
|
870
|
+
{II}AasTypes.{cls_name}
|
|
871
|
+
{I}>(
|
|
872
|
+
{II}"The required property 'modelType' is missing"
|
|
873
|
+
{I});
|
|
874
|
+
}} else if (setter.{prop_name} != "{model_type}") {{
|
|
875
|
+
{I}return newDeserializationError<
|
|
876
|
+
{II}AasTypes.{cls_name}
|
|
877
|
+
{I}>(
|
|
878
|
+
{II}"Expected model type '{model_type}', " +
|
|
879
|
+
{II}`but got: ${{setter.{prop_name}}}`
|
|
880
|
+
{I});
|
|
881
|
+
}}"""
|
|
882
|
+
)
|
|
883
|
+
)
|
|
884
|
+
|
|
885
|
+
# region Pass in arguments to the constructor
|
|
886
|
+
|
|
887
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
888
|
+
|
|
889
|
+
if len(cls.constructor.arguments) == 0:
|
|
890
|
+
blocks.append(
|
|
891
|
+
Stripped(
|
|
892
|
+
f"""\
|
|
893
|
+
return new AasCommon.Either<
|
|
894
|
+
{I}AasTypes.{cls_name},
|
|
895
|
+
{I}DeserializationError
|
|
896
|
+
>(
|
|
897
|
+
{I}new AasTypes.{cls_name}(),
|
|
898
|
+
{I}null
|
|
899
|
+
);"""
|
|
900
|
+
)
|
|
901
|
+
)
|
|
902
|
+
else:
|
|
903
|
+
init_writer = io.StringIO()
|
|
904
|
+
init_writer.write(
|
|
905
|
+
f"""\
|
|
906
|
+
return new AasCommon.Either<
|
|
907
|
+
{I}AasTypes.{cls_name},
|
|
908
|
+
{I}DeserializationError
|
|
909
|
+
>(
|
|
910
|
+
{I}new AasTypes.{cls_name}(
|
|
911
|
+
"""
|
|
912
|
+
)
|
|
913
|
+
|
|
914
|
+
for i, arg in enumerate(cls.constructor.arguments):
|
|
915
|
+
prop = cls.properties_by_name[arg.name]
|
|
916
|
+
|
|
917
|
+
prop_name = typescript_naming.property_name(prop.name)
|
|
918
|
+
|
|
919
|
+
init_writer.write(f"{II}setter.{prop_name}")
|
|
920
|
+
|
|
921
|
+
if i < len(cls.constructor.arguments) - 1:
|
|
922
|
+
init_writer.write(",\n")
|
|
923
|
+
else:
|
|
924
|
+
init_writer.write("\n")
|
|
925
|
+
|
|
926
|
+
init_writer.write(
|
|
927
|
+
f"""\
|
|
928
|
+
{I}),
|
|
929
|
+
{I}null
|
|
930
|
+
);"""
|
|
931
|
+
)
|
|
932
|
+
|
|
933
|
+
blocks.append(Stripped(init_writer.getvalue()))
|
|
934
|
+
# endregion
|
|
935
|
+
|
|
936
|
+
writer = io.StringIO()
|
|
937
|
+
|
|
938
|
+
if len(cls._concrete_descendants) == 0:
|
|
939
|
+
function_name = typescript_naming.function_name(
|
|
940
|
+
Identifier(f"{cls.name}_from_jsonable")
|
|
941
|
+
)
|
|
942
|
+
else:
|
|
943
|
+
function_name = typescript_naming.function_name(
|
|
944
|
+
Identifier(f"{cls.name}_from_jsonable_without_dispatch")
|
|
945
|
+
)
|
|
946
|
+
|
|
947
|
+
description_blocks = [
|
|
948
|
+
Stripped(
|
|
949
|
+
f"""\
|
|
950
|
+
Parse an instance of {{@link {typescript_common.TYPES_MODULE}!{cls_name}}} from the JSON-able
|
|
951
|
+
structure `jsonable`."""
|
|
952
|
+
)
|
|
953
|
+
] # type: List[Stripped]
|
|
954
|
+
|
|
955
|
+
if len(cls.concrete_descendants) > 0:
|
|
956
|
+
function_name_with_dispatch = typescript_naming.function_name(
|
|
957
|
+
Identifier(f"{cls.name}_from_jsonable")
|
|
958
|
+
)
|
|
959
|
+
|
|
960
|
+
description_blocks.append(
|
|
961
|
+
Stripped(
|
|
962
|
+
f"""\
|
|
963
|
+
This function performs no dispatch! It is used to parse the properties
|
|
964
|
+
as-are, and already assumes the exact model type. Usually, this function
|
|
965
|
+
is called from within a dispatching function, and you never call it
|
|
966
|
+
directly. If you want to de-serialize an instance of
|
|
967
|
+
{{@link {typescript_common.TYPES_MODULE}!{cls_name}}}, call
|
|
968
|
+
{{@link {function_name_with_dispatch}}}."""
|
|
969
|
+
)
|
|
970
|
+
)
|
|
971
|
+
|
|
972
|
+
description_blocks.append(
|
|
973
|
+
Stripped(
|
|
974
|
+
f"""\
|
|
975
|
+
@param jsonable - structure to be parsed
|
|
976
|
+
@returns parsed instance of {{@link {typescript_common.TYPES_MODULE}!{cls_name}}},
|
|
977
|
+
or an error if any"""
|
|
978
|
+
)
|
|
979
|
+
)
|
|
980
|
+
|
|
981
|
+
description = "\n\n".join(description_blocks)
|
|
982
|
+
description_comment = typescript_description.documentation_comment(
|
|
983
|
+
Stripped(description)
|
|
984
|
+
)
|
|
985
|
+
|
|
986
|
+
# NOTE (mristin, 2022-11-30):
|
|
987
|
+
# We export it only if the de-serialization of the class is equivalent to
|
|
988
|
+
# the de-serialization without a dispatch.
|
|
989
|
+
maybe_export_prefix = "export " if len(cls.concrete_descendants) == 0 else ""
|
|
990
|
+
|
|
991
|
+
writer.write(
|
|
992
|
+
f"""\
|
|
993
|
+
{description_comment}
|
|
994
|
+
{maybe_export_prefix}function {function_name}(
|
|
995
|
+
{I}jsonable: JsonValue
|
|
996
|
+
): AasCommon.Either<
|
|
997
|
+
{I}AasTypes.{cls_name},
|
|
998
|
+
{I}DeserializationError
|
|
999
|
+
> {{
|
|
1000
|
+
"""
|
|
1001
|
+
)
|
|
1002
|
+
|
|
1003
|
+
for i, block in enumerate(blocks):
|
|
1004
|
+
if i > 0:
|
|
1005
|
+
writer.write("\n\n")
|
|
1006
|
+
writer.write(textwrap.indent(block, I))
|
|
1007
|
+
|
|
1008
|
+
writer.write("\n}")
|
|
1009
|
+
|
|
1010
|
+
return Stripped(writer.getvalue())
|
|
1011
|
+
|
|
1012
|
+
|
|
1013
|
+
# endregion
|
|
1014
|
+
|
|
1015
|
+
# region Serialization
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
def _generate_transform_atomic_value(
|
|
1019
|
+
access_expression: str, type_anno: intermediate.AtomicTypeAnnotation
|
|
1020
|
+
) -> Stripped:
|
|
1021
|
+
"""
|
|
1022
|
+
Generate the snippet to transform the ``access_expression``.
|
|
1023
|
+
|
|
1024
|
+
The ``access_expression`` should either be a name or a member access.
|
|
1025
|
+
"""
|
|
1026
|
+
if isinstance(type_anno, intermediate.PrimitiveTypeAnnotation) or (
|
|
1027
|
+
isinstance(type_anno, intermediate.OurTypeAnnotation)
|
|
1028
|
+
and isinstance(type_anno.our_type, intermediate.ConstrainedPrimitive)
|
|
1029
|
+
):
|
|
1030
|
+
a_type = intermediate.try_primitive_type(type_anno)
|
|
1031
|
+
assert a_type is not None
|
|
1032
|
+
|
|
1033
|
+
if (
|
|
1034
|
+
a_type is intermediate.PrimitiveType.BOOL
|
|
1035
|
+
or a_type is intermediate.PrimitiveType.INT
|
|
1036
|
+
or a_type is intermediate.PrimitiveType.FLOAT
|
|
1037
|
+
or a_type is intermediate.PrimitiveType.STR
|
|
1038
|
+
):
|
|
1039
|
+
return Stripped(f"{access_expression}")
|
|
1040
|
+
|
|
1041
|
+
elif a_type is intermediate.PrimitiveType.BYTEARRAY:
|
|
1042
|
+
return Stripped(f"AasCommon.base64Encode({access_expression})")
|
|
1043
|
+
|
|
1044
|
+
else:
|
|
1045
|
+
assert_never(a_type)
|
|
1046
|
+
|
|
1047
|
+
elif isinstance(type_anno, intermediate.OurTypeAnnotation):
|
|
1048
|
+
if isinstance(type_anno.our_type, intermediate.Enumeration):
|
|
1049
|
+
must_to_str_name = typescript_naming.function_name(
|
|
1050
|
+
Identifier(f"must_{type_anno.our_type.name}_to_string")
|
|
1051
|
+
)
|
|
1052
|
+
|
|
1053
|
+
return Stripped(
|
|
1054
|
+
f"""\
|
|
1055
|
+
AasStringification.{must_to_str_name}(
|
|
1056
|
+
{I}{indent_but_first_line(access_expression, I)}
|
|
1057
|
+
)"""
|
|
1058
|
+
)
|
|
1059
|
+
|
|
1060
|
+
elif isinstance(type_anno.our_type, intermediate.ConstrainedPrimitive):
|
|
1061
|
+
raise AssertionError("This case should have been handled before.")
|
|
1062
|
+
|
|
1063
|
+
elif isinstance(
|
|
1064
|
+
type_anno.our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
|
|
1065
|
+
):
|
|
1066
|
+
return Stripped(f"this.transform({access_expression})")
|
|
1067
|
+
|
|
1068
|
+
else:
|
|
1069
|
+
assert_never(type_anno.our_type)
|
|
1070
|
+
|
|
1071
|
+
else:
|
|
1072
|
+
assert_never(type_anno.our_type)
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
def _generate_transform(cls: intermediate.ConcreteClass) -> Stripped:
|
|
1076
|
+
"""Generate the ``transformX`` method to serialize an instance into a JSON-able."""
|
|
1077
|
+
blocks = [Stripped("const jsonable: JsonObject = {};")] # type: List[Stripped]
|
|
1078
|
+
|
|
1079
|
+
for prop in cls.properties:
|
|
1080
|
+
key_literal = typescript_common.string_literal(naming.json_property(prop.name))
|
|
1081
|
+
prop_name = typescript_naming.property_name(prop.name)
|
|
1082
|
+
|
|
1083
|
+
type_anno = intermediate.beneath_optional(prop.type_annotation)
|
|
1084
|
+
|
|
1085
|
+
block: Stripped
|
|
1086
|
+
|
|
1087
|
+
if isinstance(
|
|
1088
|
+
type_anno,
|
|
1089
|
+
(intermediate.PrimitiveTypeAnnotation, intermediate.OurTypeAnnotation),
|
|
1090
|
+
):
|
|
1091
|
+
transformation_expression = _generate_transform_atomic_value(
|
|
1092
|
+
access_expression=Stripped(f"that.{prop_name}"), type_anno=type_anno
|
|
1093
|
+
)
|
|
1094
|
+
|
|
1095
|
+
block = Stripped(
|
|
1096
|
+
f"""\
|
|
1097
|
+
jsonable[{key_literal}] =
|
|
1098
|
+
{I}{indent_but_first_line(transformation_expression, I)};"""
|
|
1099
|
+
)
|
|
1100
|
+
|
|
1101
|
+
elif isinstance(type_anno, intermediate.ListTypeAnnotation):
|
|
1102
|
+
assert isinstance(
|
|
1103
|
+
type_anno.items,
|
|
1104
|
+
(intermediate.PrimitiveType, intermediate.OurTypeAnnotation),
|
|
1105
|
+
), (
|
|
1106
|
+
"We expect only lists of primitive and our types. Lists of optionals "
|
|
1107
|
+
"and nested lists are not handled yet. Please contact the developers."
|
|
1108
|
+
)
|
|
1109
|
+
|
|
1110
|
+
transformation_expression = _generate_transform_atomic_value(
|
|
1111
|
+
access_expression=Stripped("item"), type_anno=type_anno.items
|
|
1112
|
+
)
|
|
1113
|
+
|
|
1114
|
+
var_name = typescript_naming.variable_name(Identifier(f"{prop.name}_array"))
|
|
1115
|
+
|
|
1116
|
+
block = Stripped(
|
|
1117
|
+
f"""\
|
|
1118
|
+
const {var_name} = new Array<JsonObject>();
|
|
1119
|
+
for (const item of that.{prop_name}) {{
|
|
1120
|
+
{I}{var_name}.push(
|
|
1121
|
+
{II}{indent_but_first_line(transformation_expression, II)}
|
|
1122
|
+
{I});
|
|
1123
|
+
}}
|
|
1124
|
+
jsonable[{key_literal}] = {var_name};"""
|
|
1125
|
+
)
|
|
1126
|
+
|
|
1127
|
+
else:
|
|
1128
|
+
assert_never(type_anno)
|
|
1129
|
+
|
|
1130
|
+
if isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation):
|
|
1131
|
+
block = Stripped(
|
|
1132
|
+
f"""\
|
|
1133
|
+
if (that.{prop_name} !== null) {{
|
|
1134
|
+
{I}{indent_but_first_line(block, I)}
|
|
1135
|
+
}}"""
|
|
1136
|
+
)
|
|
1137
|
+
|
|
1138
|
+
blocks.append(block)
|
|
1139
|
+
|
|
1140
|
+
if cls.serialization.with_model_type:
|
|
1141
|
+
model_type_literal = typescript_common.string_literal(
|
|
1142
|
+
naming.json_model_type(cls.name)
|
|
1143
|
+
)
|
|
1144
|
+
blocks.append(Stripped(f"""jsonable["modelType"] = {model_type_literal};"""))
|
|
1145
|
+
|
|
1146
|
+
blocks.append(Stripped("return jsonable;"))
|
|
1147
|
+
|
|
1148
|
+
method_name = typescript_naming.method_name(Identifier(f"transform_{cls.name}"))
|
|
1149
|
+
|
|
1150
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
1151
|
+
|
|
1152
|
+
writer = io.StringIO()
|
|
1153
|
+
|
|
1154
|
+
writer.write(
|
|
1155
|
+
f"""\
|
|
1156
|
+
/**
|
|
1157
|
+
* Serialize `that` to a JSON-able representation.
|
|
1158
|
+
*
|
|
1159
|
+
* @param that - instance to be serialization
|
|
1160
|
+
* @returns JSON-able representation
|
|
1161
|
+
*/
|
|
1162
|
+
{method_name}(
|
|
1163
|
+
{I}that: AasTypes.{cls_name}
|
|
1164
|
+
): JsonObject {{
|
|
1165
|
+
"""
|
|
1166
|
+
)
|
|
1167
|
+
|
|
1168
|
+
for i, block in enumerate(blocks):
|
|
1169
|
+
if i > 0:
|
|
1170
|
+
writer.write("\n\n")
|
|
1171
|
+
writer.write(textwrap.indent(block, I))
|
|
1172
|
+
|
|
1173
|
+
writer.write("\n}")
|
|
1174
|
+
|
|
1175
|
+
return Stripped(writer.getvalue())
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
def _generate_transformer(symbol_table: intermediate.SymbolTable) -> Stripped:
|
|
1179
|
+
methods = [] # type: List[Stripped]
|
|
1180
|
+
|
|
1181
|
+
for cls in symbol_table.concrete_classes:
|
|
1182
|
+
methods.append(_generate_transform(cls))
|
|
1183
|
+
|
|
1184
|
+
writer = io.StringIO()
|
|
1185
|
+
writer.write(
|
|
1186
|
+
"""\
|
|
1187
|
+
/**
|
|
1188
|
+
* Transform the instance to its JSON-able representation.
|
|
1189
|
+
*/
|
|
1190
|
+
class Serializer extends AasTypes.AbstractTransformer<JsonObject> {
|
|
1191
|
+
"""
|
|
1192
|
+
)
|
|
1193
|
+
|
|
1194
|
+
for method in methods:
|
|
1195
|
+
writer.write("\n\n")
|
|
1196
|
+
writer.write(textwrap.indent(method, I))
|
|
1197
|
+
|
|
1198
|
+
writer.write("\n}")
|
|
1199
|
+
|
|
1200
|
+
return Stripped(writer.getvalue())
|
|
1201
|
+
|
|
1202
|
+
|
|
1203
|
+
# endregion
|
|
1204
|
+
|
|
1205
|
+
# fmt: off
|
|
1206
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
1207
|
+
@ensure(
|
|
1208
|
+
lambda result:
|
|
1209
|
+
not (result[0] is not None) or result[0].endswith('\n'),
|
|
1210
|
+
"Trailing newline mandatory for valid end-of-files"
|
|
1211
|
+
)
|
|
1212
|
+
# fmt: on
|
|
1213
|
+
def generate(
|
|
1214
|
+
symbol_table: intermediate.SymbolTable,
|
|
1215
|
+
spec_impls: specific_implementations.SpecificImplementations,
|
|
1216
|
+
) -> Tuple[Optional[str], Optional[List[Error]]]:
|
|
1217
|
+
"""Generate the TypeScript code for the general de/serialization."""
|
|
1218
|
+
blocks = [
|
|
1219
|
+
typescript_description.documentation_comment(
|
|
1220
|
+
Stripped(
|
|
1221
|
+
"""\
|
|
1222
|
+
Provide de/serialization of AAS classes to/from JSON.
|
|
1223
|
+
|
|
1224
|
+
We can not use one-pass deserialization for JSON since the object
|
|
1225
|
+
properties do not have fixed order, and hence we can not read
|
|
1226
|
+
`modelType` property ahead of the remaining properties."""
|
|
1227
|
+
)
|
|
1228
|
+
),
|
|
1229
|
+
typescript_common.WARNING,
|
|
1230
|
+
Stripped(
|
|
1231
|
+
"""\
|
|
1232
|
+
import * as AasCommon from "./common";
|
|
1233
|
+
import * as AasTypes from "./types";
|
|
1234
|
+
import * as AasStringification from "./stringification";"""
|
|
1235
|
+
),
|
|
1236
|
+
Stripped(
|
|
1237
|
+
"""\
|
|
1238
|
+
export type JsonValue = string | number | boolean | JsonObject | JsonArray;
|
|
1239
|
+
|
|
1240
|
+
export type JsonArray = Iterable<JsonValue>;
|
|
1241
|
+
export type JsonObject = { [prop: string]: JsonValue };"""
|
|
1242
|
+
),
|
|
1243
|
+
Stripped(
|
|
1244
|
+
f"""\
|
|
1245
|
+
/**
|
|
1246
|
+
* Represent a property on a path to the erroneous value.
|
|
1247
|
+
*/
|
|
1248
|
+
export class PropertySegment {{
|
|
1249
|
+
{I}/**
|
|
1250
|
+
{I} * Instance that contains the property
|
|
1251
|
+
{I} */
|
|
1252
|
+
{I}readonly instance: JsonObject;
|
|
1253
|
+
|
|
1254
|
+
{I}/**
|
|
1255
|
+
{I} * Name of the property
|
|
1256
|
+
{I} */
|
|
1257
|
+
{I}readonly name: string;
|
|
1258
|
+
|
|
1259
|
+
{I}constructor(instance: JsonObject, name: string) {{
|
|
1260
|
+
{II}this.instance = instance;
|
|
1261
|
+
{II}this.name = name;
|
|
1262
|
+
{I}}}
|
|
1263
|
+
}}"""
|
|
1264
|
+
),
|
|
1265
|
+
Stripped(
|
|
1266
|
+
f"""\
|
|
1267
|
+
/**
|
|
1268
|
+
* Represent an index access on a path to the erroneous value.
|
|
1269
|
+
*/
|
|
1270
|
+
export class IndexSegment {{
|
|
1271
|
+
{I}/**
|
|
1272
|
+
{I} * Container that contains the item
|
|
1273
|
+
{I} */
|
|
1274
|
+
{I}readonly container: JsonArray;
|
|
1275
|
+
|
|
1276
|
+
{I}/**
|
|
1277
|
+
{I} * Index of the item
|
|
1278
|
+
{I} */
|
|
1279
|
+
{I}readonly index: number;
|
|
1280
|
+
|
|
1281
|
+
{I}constructor(container: JsonArray, index: number) {{
|
|
1282
|
+
{II}if (!Number.isInteger(index)) {{
|
|
1283
|
+
{III}throw new Error(`Expected an integer for the index, but got: ${{index}}`);
|
|
1284
|
+
{II}}}
|
|
1285
|
+
|
|
1286
|
+
{II}this.container = container;
|
|
1287
|
+
{II}this.index = index;
|
|
1288
|
+
{I}}}
|
|
1289
|
+
}}"""
|
|
1290
|
+
),
|
|
1291
|
+
Stripped(
|
|
1292
|
+
"""\
|
|
1293
|
+
export type Segment = PropertySegment | IndexSegment;"""
|
|
1294
|
+
),
|
|
1295
|
+
Stripped(
|
|
1296
|
+
f"""\
|
|
1297
|
+
/**
|
|
1298
|
+
* Represent the relative path to the erroneous value.
|
|
1299
|
+
*/
|
|
1300
|
+
export class Path {{
|
|
1301
|
+
{I}private readonly _segments = new Array<Segment>();
|
|
1302
|
+
|
|
1303
|
+
{I}/**
|
|
1304
|
+
{I} * Get the segments of the path.
|
|
1305
|
+
{I} */
|
|
1306
|
+
{I}segments(): Array<Segment> {{
|
|
1307
|
+
{II}return this._segments;
|
|
1308
|
+
{I}}}
|
|
1309
|
+
|
|
1310
|
+
{I}/**
|
|
1311
|
+
{I} * Insert the `segment` in front of the {{@link segments}}.
|
|
1312
|
+
{I} *
|
|
1313
|
+
{I} * @param segment - segment to be prepended to {{@link segments}}
|
|
1314
|
+
{I} */
|
|
1315
|
+
{I}prepend(segment: Segment): void {{
|
|
1316
|
+
{II}this._segments.unshift(segment);
|
|
1317
|
+
{I}}}
|
|
1318
|
+
|
|
1319
|
+
{I}toString(): string {{
|
|
1320
|
+
{II}if (this._segments.length === 0) {{
|
|
1321
|
+
{III}return "";
|
|
1322
|
+
{II}}}
|
|
1323
|
+
|
|
1324
|
+
{II}const parts = new Array<string>();
|
|
1325
|
+
|
|
1326
|
+
{II}let segment = this._segments[0];
|
|
1327
|
+
|
|
1328
|
+
{II}if (segment instanceof PropertySegment) {{
|
|
1329
|
+
{III}parts.push(segment.name);
|
|
1330
|
+
{II}}} else if (segment instanceof IndexSegment) {{
|
|
1331
|
+
{III}parts.push(`[${{segment.index}}]`);
|
|
1332
|
+
{II}}} else {{
|
|
1333
|
+
{III}throw new Error(`Unexpected segment: ${{segment}}`);
|
|
1334
|
+
{II}}}
|
|
1335
|
+
|
|
1336
|
+
{II}for (let i = 1; i < this._segments.length; i++) {{
|
|
1337
|
+
{III}segment = this._segments[i];
|
|
1338
|
+
{III}if (segment instanceof PropertySegment) {{
|
|
1339
|
+
{IIII}parts.push(`.${{segment.name}}`);
|
|
1340
|
+
{III}}} else if (segment instanceof IndexSegment) {{
|
|
1341
|
+
{IIII}parts.push(`[${{segment.index}}]`);
|
|
1342
|
+
{III}}} else {{
|
|
1343
|
+
{IIII}throw new Error(`Unexpected segment: ${{segment}}`);
|
|
1344
|
+
{III}}}
|
|
1345
|
+
{II}}}
|
|
1346
|
+
|
|
1347
|
+
{II}return parts.join("");
|
|
1348
|
+
{I}}}
|
|
1349
|
+
}}"""
|
|
1350
|
+
),
|
|
1351
|
+
Stripped("// region De-serialization"),
|
|
1352
|
+
Stripped(
|
|
1353
|
+
f"""\
|
|
1354
|
+
/**
|
|
1355
|
+
* Signal that the JSON de-serialization could not be performed.
|
|
1356
|
+
*/
|
|
1357
|
+
export class DeserializationError {{
|
|
1358
|
+
{I}/**
|
|
1359
|
+
{I} * Human-readable explanation of the error
|
|
1360
|
+
{I} */
|
|
1361
|
+
{I}readonly message: string;
|
|
1362
|
+
|
|
1363
|
+
{I}/**
|
|
1364
|
+
{I} * Relative path to the erroneous value
|
|
1365
|
+
{I} */
|
|
1366
|
+
{I}readonly path: Path;
|
|
1367
|
+
|
|
1368
|
+
{I}constructor(message: string, path: Path | null = null) {{
|
|
1369
|
+
{II}this.message = message;
|
|
1370
|
+
{II}this.path = path ?? new Path();
|
|
1371
|
+
{I}}}
|
|
1372
|
+
}}"""
|
|
1373
|
+
),
|
|
1374
|
+
Stripped(
|
|
1375
|
+
f"""\
|
|
1376
|
+
/**
|
|
1377
|
+
* Create an error as {{@link common.Either}}.
|
|
1378
|
+
*
|
|
1379
|
+
* @param message - human-readable explanation of the error
|
|
1380
|
+
* @returns An {{@link common.Either }} with the error set
|
|
1381
|
+
* @typeParam T - type of the value if there had been no error
|
|
1382
|
+
*/
|
|
1383
|
+
function newDeserializationError<T>(
|
|
1384
|
+
{I}message: string
|
|
1385
|
+
): AasCommon.Either<T, DeserializationError> {{
|
|
1386
|
+
{I}return new AasCommon.Either<T, DeserializationError>(
|
|
1387
|
+
{II}null,
|
|
1388
|
+
{II}new DeserializationError(message)
|
|
1389
|
+
{I});
|
|
1390
|
+
}}"""
|
|
1391
|
+
),
|
|
1392
|
+
_generate_bool_from_jsonable(),
|
|
1393
|
+
_generate_int_from_jsonable(),
|
|
1394
|
+
_generate_float_from_jsonable(),
|
|
1395
|
+
_generate_str_from_jsonable(),
|
|
1396
|
+
_generate_bytes_from_jsonable(),
|
|
1397
|
+
] # type: List[Stripped]
|
|
1398
|
+
|
|
1399
|
+
errors = [] # type: List[Error]
|
|
1400
|
+
|
|
1401
|
+
for our_type in symbol_table.our_types:
|
|
1402
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
1403
|
+
blocks.append(_generate_enumeration_from_jsonable(enumeration=our_type))
|
|
1404
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
1405
|
+
pass
|
|
1406
|
+
elif isinstance(our_type, intermediate.AbstractClass):
|
|
1407
|
+
blocks.append(
|
|
1408
|
+
_generate_dispatch_from_jsonable(interface=our_type.interface)
|
|
1409
|
+
)
|
|
1410
|
+
elif isinstance(our_type, intermediate.ConcreteClass):
|
|
1411
|
+
if len(our_type.concrete_descendants) > 0:
|
|
1412
|
+
assert our_type.interface is not None
|
|
1413
|
+
blocks.append(
|
|
1414
|
+
_generate_dispatch_from_jsonable(interface=our_type.interface)
|
|
1415
|
+
)
|
|
1416
|
+
|
|
1417
|
+
if our_type.is_implementation_specific:
|
|
1418
|
+
implementation_key = specific_implementations.ImplementationKey(
|
|
1419
|
+
f"Jsonization/{our_type.name}_from_jsonable.ts"
|
|
1420
|
+
)
|
|
1421
|
+
|
|
1422
|
+
implementation = spec_impls.get(implementation_key, None)
|
|
1423
|
+
if implementation is None:
|
|
1424
|
+
errors.append(
|
|
1425
|
+
Error(
|
|
1426
|
+
our_type.parsed.node,
|
|
1427
|
+
f"The jsonization snippet is missing "
|
|
1428
|
+
f"for the implementation-specific "
|
|
1429
|
+
f"class {our_type.name}: {implementation_key}",
|
|
1430
|
+
)
|
|
1431
|
+
)
|
|
1432
|
+
continue
|
|
1433
|
+
else:
|
|
1434
|
+
# NOTE (mristin, 2022-11-25):
|
|
1435
|
+
# While TypeScript supports ``switch`` statement, it is not guaranteed
|
|
1436
|
+
# to run in sublinear time. Hence, we have to create a map with set
|
|
1437
|
+
# methods, see:
|
|
1438
|
+
# https://stackoverflow.com/questions/41109196/is-javascript-switch-statement-linear-or-constant-time
|
|
1439
|
+
blocks.append(_generate_setter(cls=our_type))
|
|
1440
|
+
|
|
1441
|
+
blocks.append(_generate_concrete_class_from_jsonable(cls=our_type))
|
|
1442
|
+
else:
|
|
1443
|
+
assert_never(our_type)
|
|
1444
|
+
|
|
1445
|
+
# NOTE (mristin, 2022-11-25):
|
|
1446
|
+
# We add all the dispatch mappings at the end as the functions might not have been
|
|
1447
|
+
# defined yet.
|
|
1448
|
+
for cls in symbol_table.classes:
|
|
1449
|
+
if isinstance(cls, intermediate.AbstractClass):
|
|
1450
|
+
blocks.append(_generate_dispatch_map_for_interface(interface=cls.interface))
|
|
1451
|
+
elif isinstance(cls, intermediate.ConcreteClass):
|
|
1452
|
+
if len(cls.concrete_descendants) > 0:
|
|
1453
|
+
assert (
|
|
1454
|
+
cls.interface is not None
|
|
1455
|
+
), "Expected an interface on a class with concrete descendants"
|
|
1456
|
+
|
|
1457
|
+
blocks.append(
|
|
1458
|
+
_generate_dispatch_map_for_interface(interface=cls.interface)
|
|
1459
|
+
)
|
|
1460
|
+
|
|
1461
|
+
if not cls.is_implementation_specific:
|
|
1462
|
+
blocks.append(_generate_setter_map(cls=cls))
|
|
1463
|
+
|
|
1464
|
+
else:
|
|
1465
|
+
assert_never(cls)
|
|
1466
|
+
|
|
1467
|
+
blocks.append(Stripped("// endregion"))
|
|
1468
|
+
|
|
1469
|
+
blocks.append(Stripped("// region Serialization"))
|
|
1470
|
+
|
|
1471
|
+
blocks.append(_generate_transformer(symbol_table=symbol_table))
|
|
1472
|
+
|
|
1473
|
+
blocks.append(Stripped("const SERIALIZER = new Serializer();"))
|
|
1474
|
+
|
|
1475
|
+
# pylint: disable=line-too-long
|
|
1476
|
+
blocks.append(
|
|
1477
|
+
Stripped(
|
|
1478
|
+
f"""\
|
|
1479
|
+
/**
|
|
1480
|
+
* Convert `that` to a JSON-able structure.
|
|
1481
|
+
*
|
|
1482
|
+
* @param that - AAS data to be recursively converted to a JSON-able structure
|
|
1483
|
+
* @returns
|
|
1484
|
+
* JSON-able structure which can be further processed with, say,
|
|
1485
|
+
* {{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify|JSON.stringify}})
|
|
1486
|
+
*/
|
|
1487
|
+
export function toJsonable(that: AasTypes.Class): JsonObject {{
|
|
1488
|
+
{I}return SERIALIZER.transform(that);
|
|
1489
|
+
}}"""
|
|
1490
|
+
)
|
|
1491
|
+
)
|
|
1492
|
+
# pylint: enable=line-too-long
|
|
1493
|
+
|
|
1494
|
+
blocks.append(Stripped("// endregion"))
|
|
1495
|
+
|
|
1496
|
+
if len(errors) > 0:
|
|
1497
|
+
return None, errors
|
|
1498
|
+
|
|
1499
|
+
blocks.append(typescript_common.WARNING)
|
|
1500
|
+
|
|
1501
|
+
writer = io.StringIO()
|
|
1502
|
+
for i, block in enumerate(blocks):
|
|
1503
|
+
if i > 0:
|
|
1504
|
+
writer.write("\n\n")
|
|
1505
|
+
|
|
1506
|
+
writer.write(block)
|
|
1507
|
+
|
|
1508
|
+
writer.write("\n")
|
|
1509
|
+
|
|
1510
|
+
return writer.getvalue(), None
|