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,2500 @@
|
|
|
1
|
+
"""Generate the TypeScript data structures from the intermediate representation."""
|
|
2
|
+
import io
|
|
3
|
+
import textwrap
|
|
4
|
+
from typing import (
|
|
5
|
+
Optional,
|
|
6
|
+
Dict,
|
|
7
|
+
List,
|
|
8
|
+
Tuple,
|
|
9
|
+
cast,
|
|
10
|
+
Union,
|
|
11
|
+
Mapping,
|
|
12
|
+
Final,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from icontract import ensure, require
|
|
16
|
+
|
|
17
|
+
from aas_core_codegen import intermediate
|
|
18
|
+
from aas_core_codegen import specific_implementations
|
|
19
|
+
from aas_core_codegen.common import (
|
|
20
|
+
Error,
|
|
21
|
+
Identifier,
|
|
22
|
+
assert_never,
|
|
23
|
+
Stripped,
|
|
24
|
+
indent_but_first_line,
|
|
25
|
+
)
|
|
26
|
+
from aas_core_codegen.intermediate import (
|
|
27
|
+
construction as intermediate_construction,
|
|
28
|
+
)
|
|
29
|
+
from aas_core_codegen.typescript import (
|
|
30
|
+
common as typescript_common,
|
|
31
|
+
naming as typescript_naming,
|
|
32
|
+
description as typescript_description,
|
|
33
|
+
unrolling as typescript_unrolling,
|
|
34
|
+
)
|
|
35
|
+
from aas_core_codegen.typescript.common import (
|
|
36
|
+
INDENT as I,
|
|
37
|
+
INDENT2 as II,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# region Checks
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _human_readable_identifier(
|
|
45
|
+
something: Union[
|
|
46
|
+
intermediate.Enumeration, intermediate.AbstractClass, intermediate.ConcreteClass
|
|
47
|
+
]
|
|
48
|
+
) -> str:
|
|
49
|
+
"""
|
|
50
|
+
Represent ``something`` in a human-readable text.
|
|
51
|
+
|
|
52
|
+
The reader should be able to trace ``something`` back to the meta-model.
|
|
53
|
+
"""
|
|
54
|
+
# NOTE (mristin, 2022-11-10):
|
|
55
|
+
# This function has been copy-pasted from
|
|
56
|
+
# :py:mod:`aas_core_codegen.python.structure._generate`. We tried to refactor it to
|
|
57
|
+
# :py:mod:`aas_core_codegen.intermediate`, but it turned out that the refactored
|
|
58
|
+
# code was nigh unreadable. So we preferred a little bit of copying to a little
|
|
59
|
+
# bit of complexity.
|
|
60
|
+
|
|
61
|
+
result: str
|
|
62
|
+
|
|
63
|
+
if isinstance(something, intermediate.Enumeration):
|
|
64
|
+
result = f"meta-model enumeration {something.name!r}"
|
|
65
|
+
elif isinstance(something, intermediate.AbstractClass):
|
|
66
|
+
result = f"meta-model abstract class {something.name!r}"
|
|
67
|
+
elif isinstance(something, intermediate.ConcreteClass):
|
|
68
|
+
result = f"meta-model concrete class {something.name!r}"
|
|
69
|
+
else:
|
|
70
|
+
assert_never(something)
|
|
71
|
+
|
|
72
|
+
return result
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _verify_intra_structure_collisions(
|
|
76
|
+
our_type: intermediate.OurType,
|
|
77
|
+
) -> Optional[Error]:
|
|
78
|
+
"""Verify that no member names collide in the TypeScript structure of our type."""
|
|
79
|
+
errors = [] # type: List[Error]
|
|
80
|
+
|
|
81
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
82
|
+
enum_literal_map = (
|
|
83
|
+
dict()
|
|
84
|
+
) # type: Dict[Identifier, intermediate.EnumerationLiteral]
|
|
85
|
+
|
|
86
|
+
for literal in our_type.literals:
|
|
87
|
+
literal_name = typescript_naming.enum_literal_name(literal.name)
|
|
88
|
+
colliding_literal = enum_literal_map.get(literal_name, None)
|
|
89
|
+
if colliding_literal is not None:
|
|
90
|
+
errors.append(
|
|
91
|
+
Error(
|
|
92
|
+
literal.parsed.node,
|
|
93
|
+
f"The TypeScript name, {literal_name!r}, "
|
|
94
|
+
f"for the literal {literal.name!r} collides with "
|
|
95
|
+
f"the TypeScript name of another "
|
|
96
|
+
f"literal {colliding_literal.name!r}",
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
else:
|
|
100
|
+
enum_literal_map[literal_name] = literal
|
|
101
|
+
|
|
102
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
103
|
+
pass
|
|
104
|
+
|
|
105
|
+
elif isinstance(our_type, intermediate.Class):
|
|
106
|
+
observed_member_names = {} # type: Dict[Identifier, str]
|
|
107
|
+
|
|
108
|
+
for prop in our_type.properties:
|
|
109
|
+
prop_name = typescript_naming.property_name(prop.name)
|
|
110
|
+
if prop_name in observed_member_names:
|
|
111
|
+
errors.append(
|
|
112
|
+
Error(
|
|
113
|
+
prop.parsed.node,
|
|
114
|
+
f"TypeScript property {prop_name!r} corresponding "
|
|
115
|
+
f"to the meta-model property {prop.name!r} collides with "
|
|
116
|
+
f"the {observed_member_names[prop_name]}",
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
else:
|
|
120
|
+
observed_member_names[prop_name] = (
|
|
121
|
+
f"TypeScript property {prop_name!r} corresponding to "
|
|
122
|
+
f"the meta-model property {prop.name!r}"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
for method in our_type.methods:
|
|
126
|
+
method_name = typescript_naming.method_name(method.name)
|
|
127
|
+
|
|
128
|
+
if method_name in observed_member_names:
|
|
129
|
+
errors.append(
|
|
130
|
+
Error(
|
|
131
|
+
method.parsed.node,
|
|
132
|
+
f"TypeScript method {method_name!r} corresponding "
|
|
133
|
+
f"to the meta-model method {method.name!r} collides with "
|
|
134
|
+
f"the {observed_member_names[method_name]}",
|
|
135
|
+
)
|
|
136
|
+
)
|
|
137
|
+
else:
|
|
138
|
+
observed_member_names[method_name] = (
|
|
139
|
+
f"TypeScript method {method_name!r} corresponding to "
|
|
140
|
+
f"the meta-model method {method.name!r}"
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
else:
|
|
144
|
+
assert_never(our_type)
|
|
145
|
+
|
|
146
|
+
if len(errors) > 0:
|
|
147
|
+
errors.append(
|
|
148
|
+
Error(
|
|
149
|
+
our_type.parsed.node,
|
|
150
|
+
f"Naming collision(s) in TypeScript code for our type {our_type.name!r}",
|
|
151
|
+
underlying=errors,
|
|
152
|
+
)
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _verify_structure_name_collisions(
|
|
159
|
+
symbol_table: intermediate.SymbolTable,
|
|
160
|
+
) -> List[Error]:
|
|
161
|
+
"""Verify that the TypeScript names of the structures do not collide."""
|
|
162
|
+
observed_structure_names: Dict[
|
|
163
|
+
Identifier,
|
|
164
|
+
Union[
|
|
165
|
+
intermediate.Enumeration,
|
|
166
|
+
intermediate.AbstractClass,
|
|
167
|
+
intermediate.ConcreteClass,
|
|
168
|
+
],
|
|
169
|
+
] = dict()
|
|
170
|
+
|
|
171
|
+
errors = [] # type: List[Error]
|
|
172
|
+
|
|
173
|
+
# region Inter-structure collisions
|
|
174
|
+
|
|
175
|
+
for our_type in symbol_table.our_types:
|
|
176
|
+
if not isinstance(
|
|
177
|
+
our_type,
|
|
178
|
+
(
|
|
179
|
+
intermediate.Enumeration,
|
|
180
|
+
intermediate.AbstractClass,
|
|
181
|
+
intermediate.ConcreteClass,
|
|
182
|
+
),
|
|
183
|
+
):
|
|
184
|
+
continue
|
|
185
|
+
|
|
186
|
+
name = typescript_naming.name_of(our_type)
|
|
187
|
+
|
|
188
|
+
other = observed_structure_names.get(name, None)
|
|
189
|
+
|
|
190
|
+
if other is not None:
|
|
191
|
+
errors.append(
|
|
192
|
+
Error(
|
|
193
|
+
our_type.parsed.node,
|
|
194
|
+
f"The TypeScript name {name!r} "
|
|
195
|
+
f"of the "
|
|
196
|
+
f"{_human_readable_identifier(our_type)} "
|
|
197
|
+
f"collides with the TypeScript name "
|
|
198
|
+
f"of the "
|
|
199
|
+
f"{_human_readable_identifier(other)}",
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
else:
|
|
203
|
+
observed_structure_names[name] = our_type
|
|
204
|
+
|
|
205
|
+
# endregion
|
|
206
|
+
|
|
207
|
+
# region Intra-structure collisions
|
|
208
|
+
|
|
209
|
+
for our_type in symbol_table.our_types:
|
|
210
|
+
collision_error = _verify_intra_structure_collisions(our_type=our_type)
|
|
211
|
+
|
|
212
|
+
if collision_error is not None:
|
|
213
|
+
errors.append(collision_error)
|
|
214
|
+
|
|
215
|
+
# endregion
|
|
216
|
+
|
|
217
|
+
return errors
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class VerifiedIntermediateSymbolTable(intermediate.SymbolTable):
|
|
221
|
+
"""Represent a verified symbol table which can be used for code generation."""
|
|
222
|
+
|
|
223
|
+
# noinspection PyInitNewSignature
|
|
224
|
+
def __new__(
|
|
225
|
+
cls, symbol_table: intermediate.SymbolTable
|
|
226
|
+
) -> "VerifiedIntermediateSymbolTable":
|
|
227
|
+
raise AssertionError("Only for type annotation")
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
@ensure(lambda result: (result[0] is None) ^ (result[1] is None))
|
|
231
|
+
def verify(
|
|
232
|
+
symbol_table: intermediate.SymbolTable,
|
|
233
|
+
) -> Tuple[Optional[VerifiedIntermediateSymbolTable], Optional[List[Error]]]:
|
|
234
|
+
"""Verify that TypeScript code can be generated from the ``symbol_table``."""
|
|
235
|
+
errors = [] # type: List[Error]
|
|
236
|
+
|
|
237
|
+
structure_name_collisions = _verify_structure_name_collisions(
|
|
238
|
+
symbol_table=symbol_table
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
errors.extend(structure_name_collisions)
|
|
242
|
+
|
|
243
|
+
if len(errors) > 0:
|
|
244
|
+
return None, errors
|
|
245
|
+
|
|
246
|
+
return cast(VerifiedIntermediateSymbolTable, symbol_table), None
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
# endregion
|
|
250
|
+
|
|
251
|
+
# region Generation
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _generate_model_type_enum(symbol_table: intermediate.SymbolTable) -> Stripped:
|
|
255
|
+
"""Generate the enumerator to represent runtime model type of an instance."""
|
|
256
|
+
blocks = []
|
|
257
|
+
|
|
258
|
+
for i, cls in enumerate(symbol_table.concrete_classes):
|
|
259
|
+
literal = typescript_naming.enum_literal_name(cls.name)
|
|
260
|
+
|
|
261
|
+
blocks.append(Stripped(f"{literal} = {i}"))
|
|
262
|
+
|
|
263
|
+
enum_name = typescript_naming.enum_name(Identifier("Model_type"))
|
|
264
|
+
|
|
265
|
+
body = ",\n".join(blocks)
|
|
266
|
+
|
|
267
|
+
return Stripped(
|
|
268
|
+
f"""\
|
|
269
|
+
/**
|
|
270
|
+
* Represent runtime model type of an instance.
|
|
271
|
+
*/
|
|
272
|
+
export enum {enum_name} {{
|
|
273
|
+
{I}{indent_but_first_line(body, I)}
|
|
274
|
+
}}"""
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def _generate_over_model_type_enum(symbol_table: intermediate.SymbolTable) -> Stripped:
|
|
279
|
+
"""Generate the iterator over the model type enumerator."""
|
|
280
|
+
blocks = []
|
|
281
|
+
|
|
282
|
+
model_type_enum = typescript_naming.enum_name(Identifier("Model_type"))
|
|
283
|
+
|
|
284
|
+
for i, cls in enumerate(symbol_table.concrete_classes):
|
|
285
|
+
literal = typescript_naming.enum_literal_name(cls.name)
|
|
286
|
+
|
|
287
|
+
blocks.append(
|
|
288
|
+
Stripped(
|
|
289
|
+
f"""\
|
|
290
|
+
yield <{model_type_enum}>{i}; // {literal}"""
|
|
291
|
+
)
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
over_model_type = typescript_naming.function_name(Identifier("over_model_type"))
|
|
295
|
+
|
|
296
|
+
body = "\n".join(blocks)
|
|
297
|
+
|
|
298
|
+
return Stripped(
|
|
299
|
+
f"""\
|
|
300
|
+
/**
|
|
301
|
+
* Iterate over the literals of {{@link {model_type_enum}}}.
|
|
302
|
+
*
|
|
303
|
+
* @remark
|
|
304
|
+
* TypeScript does not provide an elegant way to iterate over the literals, so
|
|
305
|
+
* this function helps you avoid common errors and pitfalls.
|
|
306
|
+
*
|
|
307
|
+
* @return iterator over the literals
|
|
308
|
+
*/
|
|
309
|
+
export function *{over_model_type} (
|
|
310
|
+
): Iterable<{model_type_enum}> {{
|
|
311
|
+
{I}// NOTE (mristin, 2022-12-03):
|
|
312
|
+
{I}// We yield numbers instead of literals to avoid name lookups on platforms
|
|
313
|
+
{I}// which do not provide JIT compilation of hot paths.
|
|
314
|
+
{I}{indent_but_first_line(body, I)}
|
|
315
|
+
}}"""
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
@require(lambda enumeration, literal: id(literal) in enumeration.literal_id_set)
|
|
320
|
+
@require(lambda literal: literal.description is not None)
|
|
321
|
+
def _generate_comment_for_enumeration_literal(
|
|
322
|
+
enumeration: intermediate.Enumeration,
|
|
323
|
+
literal: intermediate.EnumerationLiteral,
|
|
324
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
325
|
+
"""Generate the documentation comment for the given enumeration literal."""
|
|
326
|
+
# NOTE (mristin, 2022-10-29):
|
|
327
|
+
# We need to state the pre-condition for the second time for mypy.
|
|
328
|
+
assert literal.description is not None
|
|
329
|
+
|
|
330
|
+
# fmt: off
|
|
331
|
+
comment, errors = (
|
|
332
|
+
typescript_description.generate_documentation_comment_for_summary_remarks(
|
|
333
|
+
description=literal.description,
|
|
334
|
+
context=typescript_description.Context(
|
|
335
|
+
module=typescript_common.TYPES_MODULE,
|
|
336
|
+
cls_or_enum=enumeration
|
|
337
|
+
)
|
|
338
|
+
)
|
|
339
|
+
)
|
|
340
|
+
# fmt: on
|
|
341
|
+
|
|
342
|
+
if errors is not None:
|
|
343
|
+
return None, errors
|
|
344
|
+
|
|
345
|
+
assert comment is not None
|
|
346
|
+
|
|
347
|
+
return comment, None
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
@require(lambda cls_or_enum: cls_or_enum.description is not None)
|
|
351
|
+
def _generate_comment_for_cls_or_enum(
|
|
352
|
+
cls_or_enum: Union[intermediate.Enumeration, intermediate.ClassUnion],
|
|
353
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
354
|
+
"""Generate the docstring for our type."""
|
|
355
|
+
# NOTE (mristin, 2022-10-29):
|
|
356
|
+
# We need to state the pre-condition for the second time for mypy.
|
|
357
|
+
assert cls_or_enum.description is not None
|
|
358
|
+
|
|
359
|
+
# fmt: off
|
|
360
|
+
comment, errors = (
|
|
361
|
+
typescript_description
|
|
362
|
+
.generate_documentation_comment_for_summary_remarks_constraints(
|
|
363
|
+
description=cls_or_enum.description,
|
|
364
|
+
context=typescript_description.Context(
|
|
365
|
+
module=typescript_common.TYPES_MODULE, cls_or_enum=None
|
|
366
|
+
)
|
|
367
|
+
)
|
|
368
|
+
)
|
|
369
|
+
# fmt: on
|
|
370
|
+
|
|
371
|
+
if errors is not None:
|
|
372
|
+
return None, errors
|
|
373
|
+
|
|
374
|
+
assert comment is not None
|
|
375
|
+
|
|
376
|
+
return comment, None
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
@ensure(lambda result: (result[0] is None) ^ (result[1] is None))
|
|
380
|
+
def _generate_enum(
|
|
381
|
+
enum: intermediate.Enumeration,
|
|
382
|
+
) -> Tuple[Optional[Stripped], Optional[Error]]:
|
|
383
|
+
"""Generate the TypeScript code for the enum."""
|
|
384
|
+
writer = io.StringIO()
|
|
385
|
+
|
|
386
|
+
errors = [] # type: List[Error]
|
|
387
|
+
|
|
388
|
+
comment = None # type: Optional[Stripped]
|
|
389
|
+
if enum.description is not None:
|
|
390
|
+
comment, comment_errors = _generate_comment_for_cls_or_enum(cls_or_enum=enum)
|
|
391
|
+
|
|
392
|
+
if comment_errors:
|
|
393
|
+
errors.append(
|
|
394
|
+
Error(
|
|
395
|
+
enum.description.parsed.node,
|
|
396
|
+
f"Failed to generate the comment "
|
|
397
|
+
f"for the enumeration {enum.name!r}",
|
|
398
|
+
comment_errors,
|
|
399
|
+
)
|
|
400
|
+
)
|
|
401
|
+
else:
|
|
402
|
+
assert comment is not None
|
|
403
|
+
|
|
404
|
+
if comment is not None:
|
|
405
|
+
writer.write(comment)
|
|
406
|
+
writer.write("\n")
|
|
407
|
+
|
|
408
|
+
name = typescript_naming.enum_name(enum.name)
|
|
409
|
+
|
|
410
|
+
if len(enum.literals) == 0:
|
|
411
|
+
writer.write(f"export enum {name} {{}}")
|
|
412
|
+
else:
|
|
413
|
+
writer.write(f"export enum {name} {{\n")
|
|
414
|
+
|
|
415
|
+
for i, literal in enumerate(enum.literals):
|
|
416
|
+
if literal.description is not None:
|
|
417
|
+
comment, comment_errors = _generate_comment_for_enumeration_literal(
|
|
418
|
+
enumeration=enum, literal=literal
|
|
419
|
+
)
|
|
420
|
+
if comment_errors is not None:
|
|
421
|
+
errors.append(
|
|
422
|
+
Error(
|
|
423
|
+
literal.description.parsed.node,
|
|
424
|
+
f"Failed to generate the documentation comment "
|
|
425
|
+
f"for enumeration literal {literal.name!r}",
|
|
426
|
+
comment_errors,
|
|
427
|
+
)
|
|
428
|
+
)
|
|
429
|
+
else:
|
|
430
|
+
assert comment is not None
|
|
431
|
+
writer.write(textwrap.indent(comment, I))
|
|
432
|
+
writer.write("\n")
|
|
433
|
+
|
|
434
|
+
literal_name = typescript_naming.enum_literal_name(literal.name)
|
|
435
|
+
|
|
436
|
+
# NOTE (mristin, 2022-11-10):
|
|
437
|
+
# We optimize for comparisons instead of stringification.
|
|
438
|
+
# The stringification is delegated to a separate module, with efficient
|
|
439
|
+
# array look-ups to get the actual string value of a literal.
|
|
440
|
+
|
|
441
|
+
if i == 0:
|
|
442
|
+
writer.write(textwrap.indent(f"{literal_name} = 0", I))
|
|
443
|
+
else:
|
|
444
|
+
writer.write(textwrap.indent(f"{literal_name}", I))
|
|
445
|
+
|
|
446
|
+
if i < len(enum.literals) - 1:
|
|
447
|
+
writer.write(",")
|
|
448
|
+
|
|
449
|
+
writer.write("\n")
|
|
450
|
+
|
|
451
|
+
writer.write("}")
|
|
452
|
+
|
|
453
|
+
if len(errors) > 0:
|
|
454
|
+
return None, Error(
|
|
455
|
+
enum.parsed.node,
|
|
456
|
+
f"Failed to generate the TypeScript code for the enumeration {enum.name!r}",
|
|
457
|
+
errors,
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
return Stripped(writer.getvalue()), None
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
def _generate_over_enum(enum: intermediate.Enumeration) -> Stripped:
|
|
464
|
+
"""Generate the TypeScript code for the function to iterate over the literals."""
|
|
465
|
+
name = typescript_naming.enum_name(enum.name)
|
|
466
|
+
function_name = typescript_naming.function_name(Identifier(f"over_{enum.name}"))
|
|
467
|
+
|
|
468
|
+
statements = [
|
|
469
|
+
f"yield <{name}>{i}; // {typescript_naming.enum_literal_name(literal.name)}"
|
|
470
|
+
for i, literal in enumerate(enum.literals)
|
|
471
|
+
]
|
|
472
|
+
body = "\n".join(statements)
|
|
473
|
+
|
|
474
|
+
return Stripped(
|
|
475
|
+
f"""\
|
|
476
|
+
/**
|
|
477
|
+
* Iterate over the literals of {{@link {name}}}.
|
|
478
|
+
*
|
|
479
|
+
* @remark
|
|
480
|
+
* TypeScript does not provide an elegant way to iterate over the literals, so
|
|
481
|
+
* this function helps you avoid common errors and pitfalls.
|
|
482
|
+
*
|
|
483
|
+
* @return iterator over the literals
|
|
484
|
+
*/
|
|
485
|
+
export function *{function_name}(
|
|
486
|
+
): IterableIterator<{name}> {{
|
|
487
|
+
{I}// NOTE (mristin, 2022-12-03):
|
|
488
|
+
{I}// We yield numbers instead of literals to avoid name lookups on platforms
|
|
489
|
+
{I}// which do not provide JIT compilation of hot paths.
|
|
490
|
+
{I}{indent_but_first_line(body, I)}
|
|
491
|
+
}}"""
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
class _DescendBodyUnroller(typescript_unrolling.AbstractUnroller):
|
|
496
|
+
"""Generate the code that unrolls descent into an element."""
|
|
497
|
+
|
|
498
|
+
#: If set, generates the code with unrolled yields.
|
|
499
|
+
#: Otherwise, we do not unroll recursively.
|
|
500
|
+
_recurse: Final[bool]
|
|
501
|
+
|
|
502
|
+
#: Pre-computed descendability map. A type is descendable if we should unroll it
|
|
503
|
+
#: further.
|
|
504
|
+
_descendability: Final[Mapping[intermediate.TypeAnnotationUnion, bool]]
|
|
505
|
+
|
|
506
|
+
#: Generator of loop variable names.
|
|
507
|
+
#:
|
|
508
|
+
#: We generate for each list iteration a new variable to avoid shadowing
|
|
509
|
+
#: of the variables. Even though TypeScript tracks variables in the block scope,
|
|
510
|
+
#: we want to avoid confusion for the reader.
|
|
511
|
+
_generator_for_loop_variables: Final[typescript_common.GeneratorForLoopVariables]
|
|
512
|
+
|
|
513
|
+
def __init__(
|
|
514
|
+
self,
|
|
515
|
+
recurse: bool,
|
|
516
|
+
descendability: Mapping[intermediate.TypeAnnotationUnion, bool],
|
|
517
|
+
generator_for_loop_variables: typescript_common.GeneratorForLoopVariables,
|
|
518
|
+
) -> None:
|
|
519
|
+
"""Initialize with the given values."""
|
|
520
|
+
self._recurse = recurse
|
|
521
|
+
self._descendability = descendability
|
|
522
|
+
self._generator_for_loop_variables = generator_for_loop_variables
|
|
523
|
+
|
|
524
|
+
def _unroll_primitive_type_annotation(
|
|
525
|
+
self,
|
|
526
|
+
unrollee_expr: str,
|
|
527
|
+
type_annotation: intermediate.PrimitiveTypeAnnotation,
|
|
528
|
+
path: List[str],
|
|
529
|
+
list_loop_level: int,
|
|
530
|
+
) -> List[typescript_unrolling.Node]:
|
|
531
|
+
"""Generate code for the given specific ``type_annotation``."""
|
|
532
|
+
# We can not descend into a primitive type.
|
|
533
|
+
return []
|
|
534
|
+
|
|
535
|
+
def _unroll_our_type_annotation(
|
|
536
|
+
self,
|
|
537
|
+
unrollee_expr: str,
|
|
538
|
+
type_annotation: intermediate.OurTypeAnnotation,
|
|
539
|
+
path: List[str],
|
|
540
|
+
list_loop_level: int,
|
|
541
|
+
) -> List[typescript_unrolling.Node]:
|
|
542
|
+
"""Generate code for the given specific ``type_annotation``."""
|
|
543
|
+
our_type = type_annotation.our_type
|
|
544
|
+
|
|
545
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
546
|
+
# We can not descend into an enumeration.
|
|
547
|
+
return []
|
|
548
|
+
|
|
549
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
550
|
+
# We can not descend into a primitive type.
|
|
551
|
+
return []
|
|
552
|
+
|
|
553
|
+
assert isinstance(our_type, intermediate.Class) # Exhaustively match
|
|
554
|
+
|
|
555
|
+
result = [typescript_unrolling.Node(f"yield {unrollee_expr};", children=[])]
|
|
556
|
+
|
|
557
|
+
if self._recurse:
|
|
558
|
+
if self._descendability[type_annotation]:
|
|
559
|
+
result.append(
|
|
560
|
+
typescript_unrolling.Node(
|
|
561
|
+
text=f"yield * {unrollee_expr}.descend();",
|
|
562
|
+
children=[],
|
|
563
|
+
)
|
|
564
|
+
)
|
|
565
|
+
|
|
566
|
+
return result
|
|
567
|
+
|
|
568
|
+
def _unroll_list_type_annotation(
|
|
569
|
+
self,
|
|
570
|
+
unrollee_expr: str,
|
|
571
|
+
type_annotation: intermediate.ListTypeAnnotation,
|
|
572
|
+
path: List[str],
|
|
573
|
+
list_loop_level: int,
|
|
574
|
+
) -> List[typescript_unrolling.Node]:
|
|
575
|
+
"""Generate code for the given specific ``type_annotation``."""
|
|
576
|
+
if (
|
|
577
|
+
not self._recurse
|
|
578
|
+
and isinstance(type_annotation.items, intermediate.OurTypeAnnotation)
|
|
579
|
+
and isinstance(
|
|
580
|
+
type_annotation.items.our_type,
|
|
581
|
+
(intermediate.AbstractClass, intermediate.ConcreteClass),
|
|
582
|
+
)
|
|
583
|
+
):
|
|
584
|
+
return [typescript_unrolling.Node(f"yield * {unrollee_expr};", children=[])]
|
|
585
|
+
|
|
586
|
+
loop_var = next(self._generator_for_loop_variables)
|
|
587
|
+
children = self.unroll(
|
|
588
|
+
unrollee_expr=loop_var,
|
|
589
|
+
type_annotation=type_annotation.items,
|
|
590
|
+
path=[], # Path is unused in this context
|
|
591
|
+
list_loop_level=list_loop_level + 1,
|
|
592
|
+
)
|
|
593
|
+
|
|
594
|
+
if len(children) == 0:
|
|
595
|
+
return []
|
|
596
|
+
|
|
597
|
+
node = typescript_unrolling.Node(
|
|
598
|
+
text=f"for (const {loop_var} of {unrollee_expr})",
|
|
599
|
+
children=children,
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
return [node]
|
|
603
|
+
|
|
604
|
+
def _unroll_optional_type_annotation(
|
|
605
|
+
self,
|
|
606
|
+
unrollee_expr: str,
|
|
607
|
+
type_annotation: intermediate.OptionalTypeAnnotation,
|
|
608
|
+
path: List[str],
|
|
609
|
+
list_loop_level: int,
|
|
610
|
+
) -> List[typescript_unrolling.Node]:
|
|
611
|
+
"""Generate code for the given specific ``type_annotation``."""
|
|
612
|
+
children = self.unroll(
|
|
613
|
+
unrollee_expr=unrollee_expr,
|
|
614
|
+
type_annotation=type_annotation.value,
|
|
615
|
+
path=path,
|
|
616
|
+
list_loop_level=list_loop_level,
|
|
617
|
+
)
|
|
618
|
+
|
|
619
|
+
if len(children) == 0:
|
|
620
|
+
return []
|
|
621
|
+
|
|
622
|
+
return [
|
|
623
|
+
typescript_unrolling.Node(
|
|
624
|
+
text=f"if ({unrollee_expr} !== null)", children=children
|
|
625
|
+
)
|
|
626
|
+
]
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
def _generate_descend_body(cls: intermediate.ConcreteClass, recurse: bool) -> Stripped:
|
|
630
|
+
"""
|
|
631
|
+
Generate the body of the ``descend`` and ``descend_once`` methods.
|
|
632
|
+
|
|
633
|
+
With this function, we unroll the recursion as a simple optimization
|
|
634
|
+
in the recursive case.
|
|
635
|
+
"""
|
|
636
|
+
blocks = [] # type: List[Stripped]
|
|
637
|
+
|
|
638
|
+
generator_for_loop_variables = typescript_common.GeneratorForLoopVariables()
|
|
639
|
+
|
|
640
|
+
for prop in cls.properties:
|
|
641
|
+
descendability = intermediate.map_descendability(
|
|
642
|
+
type_annotation=prop.type_annotation
|
|
643
|
+
)
|
|
644
|
+
|
|
645
|
+
if not descendability[prop.type_annotation]:
|
|
646
|
+
continue
|
|
647
|
+
|
|
648
|
+
# region Unroll
|
|
649
|
+
|
|
650
|
+
unroller = _DescendBodyUnroller(
|
|
651
|
+
recurse=recurse,
|
|
652
|
+
descendability=descendability,
|
|
653
|
+
generator_for_loop_variables=generator_for_loop_variables,
|
|
654
|
+
)
|
|
655
|
+
|
|
656
|
+
roots = unroller.unroll(
|
|
657
|
+
unrollee_expr=f"this.{typescript_naming.property_name(prop.name)}",
|
|
658
|
+
type_annotation=prop.type_annotation,
|
|
659
|
+
path=[], # We do not use path in this context
|
|
660
|
+
list_loop_level=0,
|
|
661
|
+
)
|
|
662
|
+
|
|
663
|
+
assert len(roots) > 0, (
|
|
664
|
+
"Since the type annotation was descendable, we must have obtained "
|
|
665
|
+
"at least one unrolling node"
|
|
666
|
+
)
|
|
667
|
+
|
|
668
|
+
blocks.extend(Stripped(typescript_unrolling.render(root)) for root in roots)
|
|
669
|
+
|
|
670
|
+
# endregion
|
|
671
|
+
|
|
672
|
+
if len(blocks) == 0:
|
|
673
|
+
blocks.append(Stripped("// No descendable properties"))
|
|
674
|
+
|
|
675
|
+
return Stripped("\n\n".join(blocks))
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
def _generate_descend_once_method(cls: intermediate.ConcreteClass) -> Stripped:
|
|
679
|
+
"""Generate the ``descend_once`` method for the concrete class ``cls``."""
|
|
680
|
+
|
|
681
|
+
body = _generate_descend_body(cls=cls, recurse=False)
|
|
682
|
+
|
|
683
|
+
return Stripped(
|
|
684
|
+
f"""\
|
|
685
|
+
/**
|
|
686
|
+
* Iterate over the instances referenced from this instance.
|
|
687
|
+
*
|
|
688
|
+
* We do not recurse into the referenced instances.
|
|
689
|
+
*
|
|
690
|
+
* @returns Iterator over the referenced instances
|
|
691
|
+
*/
|
|
692
|
+
*descendOnce(): IterableIterator<Class> {{
|
|
693
|
+
{I}{indent_but_first_line(body, I)}
|
|
694
|
+
}}"""
|
|
695
|
+
)
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
def _generate_descend_method(cls: intermediate.ConcreteClass) -> Stripped:
|
|
699
|
+
"""Generate the recursive ``descend`` method for the concrete class ``cls``."""
|
|
700
|
+
|
|
701
|
+
body = _generate_descend_body(cls=cls, recurse=True)
|
|
702
|
+
|
|
703
|
+
return Stripped(
|
|
704
|
+
f"""\
|
|
705
|
+
/**
|
|
706
|
+
* Iterate recursively over the instances referenced from this instance.
|
|
707
|
+
*
|
|
708
|
+
* @returns Iterator over the referenced instances
|
|
709
|
+
*/
|
|
710
|
+
*descend(): IterableIterator<Class> {{
|
|
711
|
+
{I}{indent_but_first_line(body, I)}
|
|
712
|
+
}}"""
|
|
713
|
+
)
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
717
|
+
def _generate_default_value(
|
|
718
|
+
default: intermediate.Default,
|
|
719
|
+
) -> Tuple[Optional[Stripped], Optional[Error]]:
|
|
720
|
+
"""Generate the TypeScript code representing the default value of an argument."""
|
|
721
|
+
code: str
|
|
722
|
+
|
|
723
|
+
if isinstance(default, intermediate.DefaultPrimitive):
|
|
724
|
+
if default.value is None:
|
|
725
|
+
code = "null"
|
|
726
|
+
elif isinstance(default.value, bool):
|
|
727
|
+
code = typescript_common.boolean_literal(default.value)
|
|
728
|
+
elif isinstance(default.value, int):
|
|
729
|
+
if not typescript_common.representable_as_number(default.value):
|
|
730
|
+
return None, Error(
|
|
731
|
+
default.parsed.node,
|
|
732
|
+
f"The value is not representable as a double-precision "
|
|
733
|
+
f"floating point number: {default.value}",
|
|
734
|
+
)
|
|
735
|
+
code = typescript_common.numeric_literal(default.value)
|
|
736
|
+
elif isinstance(default.value, float):
|
|
737
|
+
code = typescript_common.numeric_literal(default.value)
|
|
738
|
+
elif isinstance(default.value, str):
|
|
739
|
+
code = typescript_common.string_literal(default.value)
|
|
740
|
+
else:
|
|
741
|
+
assert_never(default.value)
|
|
742
|
+
elif isinstance(default, intermediate.DefaultEnumerationLiteral):
|
|
743
|
+
code = ".".join(
|
|
744
|
+
[
|
|
745
|
+
typescript_naming.enum_name(default.enumeration.name),
|
|
746
|
+
typescript_naming.enum_literal_name(default.literal.name),
|
|
747
|
+
]
|
|
748
|
+
)
|
|
749
|
+
else:
|
|
750
|
+
assert_never(default)
|
|
751
|
+
|
|
752
|
+
return Stripped(code), None
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
@require(lambda cls: not cls.is_implementation_specific)
|
|
756
|
+
@require(lambda cls: not cls.constructor.is_implementation_specific)
|
|
757
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
758
|
+
def _generate_constructor(
|
|
759
|
+
cls: intermediate.ClassUnion,
|
|
760
|
+
) -> Tuple[Optional[Stripped], Optional[Error]]:
|
|
761
|
+
"""
|
|
762
|
+
Generate the constructor function for the given concrete class ``cls``.
|
|
763
|
+
|
|
764
|
+
Return empty string if there is an empty constructor.
|
|
765
|
+
"""
|
|
766
|
+
if (
|
|
767
|
+
len(cls.constructor.arguments) == 0
|
|
768
|
+
and len(cls.constructor.inlined_statements) == 0
|
|
769
|
+
):
|
|
770
|
+
return Stripped(""), None
|
|
771
|
+
|
|
772
|
+
blocks = [] # type: List[str]
|
|
773
|
+
|
|
774
|
+
arg_codes = [] # type: List[str]
|
|
775
|
+
for arg in cls.constructor.arguments:
|
|
776
|
+
arg_type = typescript_common.generate_type(type_annotation=arg.type_annotation)
|
|
777
|
+
arg_name = typescript_naming.argument_name(arg.name)
|
|
778
|
+
|
|
779
|
+
if arg.default is None:
|
|
780
|
+
arg_codes.append(Stripped(f"{arg_name}: {arg_type}"))
|
|
781
|
+
else:
|
|
782
|
+
default_value, default_value_error = _generate_default_value(arg.default)
|
|
783
|
+
if default_value_error is not None:
|
|
784
|
+
return None, Error(
|
|
785
|
+
cls.parsed.node,
|
|
786
|
+
f"Failed to generate the default value for "
|
|
787
|
+
f"the constructor argument {arg.name!r} of class {cls.name!r}",
|
|
788
|
+
[default_value_error],
|
|
789
|
+
)
|
|
790
|
+
|
|
791
|
+
assert default_value is not None
|
|
792
|
+
|
|
793
|
+
arg_codes.append(Stripped(f"{arg_name}: {arg_type} = {default_value}"))
|
|
794
|
+
|
|
795
|
+
if len(arg_codes) == 0:
|
|
796
|
+
blocks.append("constructor() {")
|
|
797
|
+
if len(arg_codes) == 1:
|
|
798
|
+
blocks.append(f"constructor({arg_codes[0]}) {{")
|
|
799
|
+
else:
|
|
800
|
+
arg_block = ",\n".join(arg_codes)
|
|
801
|
+
blocks.append(
|
|
802
|
+
Stripped(
|
|
803
|
+
f"""\
|
|
804
|
+
constructor(
|
|
805
|
+
{I}{indent_but_first_line(arg_block, I)}
|
|
806
|
+
) {{"""
|
|
807
|
+
)
|
|
808
|
+
)
|
|
809
|
+
|
|
810
|
+
body = ["super();"] # type: List[str]
|
|
811
|
+
|
|
812
|
+
for stmt in cls.constructor.inlined_statements:
|
|
813
|
+
if isinstance(stmt, intermediate_construction.AssignArgument):
|
|
814
|
+
if stmt.default is None:
|
|
815
|
+
body.append(
|
|
816
|
+
f"this.{typescript_naming.property_name(stmt.name)} = "
|
|
817
|
+
f"{typescript_naming.argument_name(stmt.argument)};"
|
|
818
|
+
)
|
|
819
|
+
else:
|
|
820
|
+
if isinstance(stmt.default, intermediate_construction.EmptyList):
|
|
821
|
+
prop = cls.properties_by_name[stmt.name]
|
|
822
|
+
|
|
823
|
+
type_anno = prop.type_annotation
|
|
824
|
+
while isinstance(type_anno, intermediate.OptionalTypeAnnotation):
|
|
825
|
+
type_anno = type_anno.value
|
|
826
|
+
|
|
827
|
+
prop_type = typescript_common.generate_type(
|
|
828
|
+
type_annotation=type_anno
|
|
829
|
+
)
|
|
830
|
+
|
|
831
|
+
arg_name = typescript_naming.argument_name(stmt.argument)
|
|
832
|
+
|
|
833
|
+
body.append(
|
|
834
|
+
f"""\
|
|
835
|
+
this.{typescript_naming.property_name(stmt.name)} = ({arg_name} !== null)
|
|
836
|
+
{I}? {arg_name}
|
|
837
|
+
{I}: new {prop_type}();"""
|
|
838
|
+
)
|
|
839
|
+
elif isinstance(
|
|
840
|
+
stmt.default, intermediate_construction.DefaultEnumLiteral
|
|
841
|
+
):
|
|
842
|
+
literal_code = ".".join(
|
|
843
|
+
[
|
|
844
|
+
typescript_naming.enum_name(stmt.default.enum.name),
|
|
845
|
+
typescript_naming.enum_literal_name(
|
|
846
|
+
stmt.default.literal.name
|
|
847
|
+
),
|
|
848
|
+
]
|
|
849
|
+
)
|
|
850
|
+
|
|
851
|
+
arg_name = typescript_naming.argument_name(stmt.argument)
|
|
852
|
+
|
|
853
|
+
body.append(
|
|
854
|
+
Stripped(
|
|
855
|
+
f"""\
|
|
856
|
+
this.{typescript_naming.property_name(stmt.name)} = ({arg_name})
|
|
857
|
+
{I}? {arg_name}
|
|
858
|
+
{I}: {literal_code};"""
|
|
859
|
+
)
|
|
860
|
+
)
|
|
861
|
+
else:
|
|
862
|
+
assert_never(stmt.default)
|
|
863
|
+
|
|
864
|
+
else:
|
|
865
|
+
assert_never(stmt)
|
|
866
|
+
|
|
867
|
+
blocks.append("\n".join(textwrap.indent(stmt_code, I) for stmt_code in body))
|
|
868
|
+
|
|
869
|
+
blocks.append("}")
|
|
870
|
+
|
|
871
|
+
return Stripped("\n".join(blocks)), None
|
|
872
|
+
|
|
873
|
+
|
|
874
|
+
@require(lambda cls, prop: id(prop) in cls.property_id_set)
|
|
875
|
+
@require(lambda prop: prop.description is not None)
|
|
876
|
+
def _generate_comment_for_property(
|
|
877
|
+
cls: intermediate.ClassUnion,
|
|
878
|
+
prop: intermediate.Property,
|
|
879
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
880
|
+
"""Generate the documentation comment for the given property."""
|
|
881
|
+
# NOTE (mristin, 2022-10-29):
|
|
882
|
+
# We need to write a double assertion for mypy.
|
|
883
|
+
assert prop.description is not None
|
|
884
|
+
|
|
885
|
+
# fmt: off
|
|
886
|
+
comment, errors = (
|
|
887
|
+
typescript_description
|
|
888
|
+
.generate_documentation_comment_for_summary_remarks_constraints(
|
|
889
|
+
description=prop.description,
|
|
890
|
+
context=typescript_description.Context(
|
|
891
|
+
module=typescript_common.TYPES_MODULE,
|
|
892
|
+
cls_or_enum=cls,
|
|
893
|
+
)
|
|
894
|
+
)
|
|
895
|
+
)
|
|
896
|
+
# fmt: on
|
|
897
|
+
|
|
898
|
+
if errors is not None:
|
|
899
|
+
return None, errors
|
|
900
|
+
|
|
901
|
+
assert comment is not None
|
|
902
|
+
|
|
903
|
+
return comment, None
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
@ensure(lambda result: (result[0] is None) ^ (result[1] is None))
|
|
907
|
+
def _generate_interface(
|
|
908
|
+
interface: intermediate.Interface,
|
|
909
|
+
) -> Tuple[Optional[Stripped], Optional[Error]]:
|
|
910
|
+
"""Generate TypeScript code for the given ``interface``."""
|
|
911
|
+
# Code blocks separated by double newlines and indented once
|
|
912
|
+
blocks = [] # type: List[Stripped]
|
|
913
|
+
|
|
914
|
+
# region Properties
|
|
915
|
+
|
|
916
|
+
for prop in interface.properties:
|
|
917
|
+
prop_type = typescript_common.generate_type(
|
|
918
|
+
type_annotation=prop.type_annotation
|
|
919
|
+
)
|
|
920
|
+
prop_name = typescript_naming.property_name(prop.name)
|
|
921
|
+
|
|
922
|
+
if prop.description is not None:
|
|
923
|
+
(
|
|
924
|
+
prop_comment,
|
|
925
|
+
prop_comment_errors,
|
|
926
|
+
) = _generate_comment_for_property(cls=interface.base, prop=prop)
|
|
927
|
+
|
|
928
|
+
if prop_comment_errors is not None:
|
|
929
|
+
return None, Error(
|
|
930
|
+
prop.description.parsed.node,
|
|
931
|
+
f"Failed to generate the documentation comment "
|
|
932
|
+
f"for the property {prop.name!r}",
|
|
933
|
+
prop_comment_errors,
|
|
934
|
+
)
|
|
935
|
+
|
|
936
|
+
blocks.append(Stripped(f"{prop_comment}\n" f"{prop_name}: {prop_type};"))
|
|
937
|
+
else:
|
|
938
|
+
blocks.append(Stripped(f"{prop_name}: {prop_type};"))
|
|
939
|
+
|
|
940
|
+
# endregion
|
|
941
|
+
|
|
942
|
+
# region Signatures
|
|
943
|
+
|
|
944
|
+
for signature in interface.signatures:
|
|
945
|
+
signature_blocks = [] # type: List[Stripped]
|
|
946
|
+
|
|
947
|
+
if signature.description is not None:
|
|
948
|
+
(
|
|
949
|
+
signature_comment,
|
|
950
|
+
signature_comment_errors,
|
|
951
|
+
) = typescript_description.generate_documentation_comment_for_signature(
|
|
952
|
+
signature.description,
|
|
953
|
+
context=typescript_description.Context(
|
|
954
|
+
module=typescript_common.TYPES_MODULE, cls_or_enum=interface.base
|
|
955
|
+
),
|
|
956
|
+
)
|
|
957
|
+
|
|
958
|
+
if signature_comment_errors is not None:
|
|
959
|
+
return None, Error(
|
|
960
|
+
signature.description.parsed.node,
|
|
961
|
+
f"Failed to generate the documentation comment "
|
|
962
|
+
f"for signature {signature.name!r}",
|
|
963
|
+
signature_comment_errors,
|
|
964
|
+
)
|
|
965
|
+
|
|
966
|
+
assert signature_comment is not None
|
|
967
|
+
|
|
968
|
+
signature_blocks.append(signature_comment)
|
|
969
|
+
|
|
970
|
+
# fmt: off
|
|
971
|
+
returns = (
|
|
972
|
+
typescript_common.generate_type(type_annotation=signature.returns)
|
|
973
|
+
if signature.returns is not None else "void"
|
|
974
|
+
)
|
|
975
|
+
# fmt: on
|
|
976
|
+
|
|
977
|
+
arg_codes = [] # type: List[Stripped]
|
|
978
|
+
for arg in signature.arguments:
|
|
979
|
+
arg_type = typescript_common.generate_type(
|
|
980
|
+
type_annotation=arg.type_annotation
|
|
981
|
+
)
|
|
982
|
+
arg_name = typescript_naming.argument_name(arg.name)
|
|
983
|
+
arg_codes.append(Stripped(f"{arg_name}: {arg_type}"))
|
|
984
|
+
|
|
985
|
+
signature_name = typescript_naming.method_name(signature.name)
|
|
986
|
+
if len(arg_codes) > 2:
|
|
987
|
+
arg_block = ",\n".join(arg_codes)
|
|
988
|
+
signature_blocks.append(
|
|
989
|
+
Stripped(
|
|
990
|
+
f"""\
|
|
991
|
+
{signature_name}(
|
|
992
|
+
{I}{indent_but_first_line(arg_block, I)}
|
|
993
|
+
): {returns};"""
|
|
994
|
+
)
|
|
995
|
+
)
|
|
996
|
+
elif len(arg_codes) == 1:
|
|
997
|
+
signature_blocks.append(
|
|
998
|
+
Stripped(f"{signature_name}({arg_codes[0]}): {returns};")
|
|
999
|
+
)
|
|
1000
|
+
else:
|
|
1001
|
+
assert len(arg_codes) == 0
|
|
1002
|
+
signature_blocks.append(Stripped(f"{signature_name}(): {returns};"))
|
|
1003
|
+
|
|
1004
|
+
blocks.append(Stripped("\n".join(signature_blocks)))
|
|
1005
|
+
|
|
1006
|
+
# region over_X_or_empty getter
|
|
1007
|
+
|
|
1008
|
+
for prop in interface.properties:
|
|
1009
|
+
if isinstance(
|
|
1010
|
+
prop.type_annotation, intermediate.OptionalTypeAnnotation
|
|
1011
|
+
) and isinstance(prop.type_annotation.value, intermediate.ListTypeAnnotation):
|
|
1012
|
+
prop_name = typescript_naming.property_name(prop.name)
|
|
1013
|
+
items_type = typescript_common.generate_type(
|
|
1014
|
+
prop.type_annotation.value.items
|
|
1015
|
+
)
|
|
1016
|
+
|
|
1017
|
+
over_x_or_empty = typescript_naming.method_name(
|
|
1018
|
+
Identifier(f"over_{prop.name}_or_empty")
|
|
1019
|
+
)
|
|
1020
|
+
|
|
1021
|
+
blocks.append(
|
|
1022
|
+
Stripped(
|
|
1023
|
+
f"""\
|
|
1024
|
+
/**
|
|
1025
|
+
* Yield from {{@link {prop_name}}} if it is set, or yield nothing.
|
|
1026
|
+
*/
|
|
1027
|
+
{over_x_or_empty}(): IterableIterator<{items_type}>;"""
|
|
1028
|
+
)
|
|
1029
|
+
)
|
|
1030
|
+
|
|
1031
|
+
# endregion
|
|
1032
|
+
|
|
1033
|
+
comment = None # type: Optional[Stripped]
|
|
1034
|
+
if interface.description is not None:
|
|
1035
|
+
# fmt: off
|
|
1036
|
+
comment, comment_errors = (
|
|
1037
|
+
typescript_description
|
|
1038
|
+
.generate_documentation_comment_for_summary_remarks_constraints(
|
|
1039
|
+
interface.description,
|
|
1040
|
+
context=typescript_description.Context(
|
|
1041
|
+
module=typescript_common.TYPES_MODULE,
|
|
1042
|
+
cls_or_enum=interface.base
|
|
1043
|
+
)
|
|
1044
|
+
)
|
|
1045
|
+
)
|
|
1046
|
+
# fmt: on
|
|
1047
|
+
|
|
1048
|
+
if comment_errors is not None:
|
|
1049
|
+
return None, Error(
|
|
1050
|
+
interface.description.parsed.node,
|
|
1051
|
+
"Failed to generate the documentation comment",
|
|
1052
|
+
comment_errors,
|
|
1053
|
+
)
|
|
1054
|
+
|
|
1055
|
+
assert comment is not None
|
|
1056
|
+
|
|
1057
|
+
empty_interface = False
|
|
1058
|
+
if len(blocks) == 0:
|
|
1059
|
+
blocks = [Stripped("// Intentionally empty.")]
|
|
1060
|
+
empty_interface = True
|
|
1061
|
+
|
|
1062
|
+
writer = io.StringIO()
|
|
1063
|
+
if comment is not None:
|
|
1064
|
+
writer.write(comment)
|
|
1065
|
+
writer.write("\n")
|
|
1066
|
+
|
|
1067
|
+
name = typescript_naming.interface_name(interface.name)
|
|
1068
|
+
|
|
1069
|
+
if empty_interface:
|
|
1070
|
+
writer.write(
|
|
1071
|
+
"// eslint-disable-next-line @typescript-eslint/no-empty-interface\n"
|
|
1072
|
+
)
|
|
1073
|
+
|
|
1074
|
+
if len(interface.inheritances) == 0:
|
|
1075
|
+
writer.write(
|
|
1076
|
+
f"""\
|
|
1077
|
+
export interface {name} extends Class {{
|
|
1078
|
+
"""
|
|
1079
|
+
)
|
|
1080
|
+
elif len(interface.inheritances) == 1:
|
|
1081
|
+
# NOTE (mristin, 2022-12-07):
|
|
1082
|
+
# We can omit Class in the list of inheritances as one of the parents already
|
|
1083
|
+
# extends it.
|
|
1084
|
+
writer.write(
|
|
1085
|
+
f"""\
|
|
1086
|
+
export interface {name}
|
|
1087
|
+
{I}extends {typescript_naming.interface_name(interface.inheritances[0].name)} {{
|
|
1088
|
+
"""
|
|
1089
|
+
)
|
|
1090
|
+
else:
|
|
1091
|
+
# NOTE (mristin, 2022-12-07):
|
|
1092
|
+
# We can omit Class in the list of inheritances as one of the parents already
|
|
1093
|
+
# extends it.
|
|
1094
|
+
writer.write(
|
|
1095
|
+
f"""\
|
|
1096
|
+
export interface {name}
|
|
1097
|
+
"""
|
|
1098
|
+
)
|
|
1099
|
+
|
|
1100
|
+
for i, inheritance in enumerate(interface.inheritances):
|
|
1101
|
+
if i == 0:
|
|
1102
|
+
writer.write(
|
|
1103
|
+
f"""\
|
|
1104
|
+
{I}extends {typescript_naming.interface_name(inheritance.name)},
|
|
1105
|
+
"""
|
|
1106
|
+
)
|
|
1107
|
+
elif i < len(interface.inheritances) - 1:
|
|
1108
|
+
writer.write(
|
|
1109
|
+
f"""\
|
|
1110
|
+
{II}{typescript_naming.interface_name(inheritance.name)},
|
|
1111
|
+
"""
|
|
1112
|
+
)
|
|
1113
|
+
else:
|
|
1114
|
+
writer.write(
|
|
1115
|
+
f"""\
|
|
1116
|
+
{II}{typescript_naming.interface_name(inheritance.name)} {{
|
|
1117
|
+
"""
|
|
1118
|
+
)
|
|
1119
|
+
|
|
1120
|
+
for i, code in enumerate(blocks):
|
|
1121
|
+
if i > 0:
|
|
1122
|
+
writer.write("\n\n")
|
|
1123
|
+
|
|
1124
|
+
writer.write(textwrap.indent(code, I))
|
|
1125
|
+
|
|
1126
|
+
writer.write("\n}")
|
|
1127
|
+
|
|
1128
|
+
return Stripped(writer.getvalue()), None
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
@require(lambda cls: not cls.is_implementation_specific)
|
|
1132
|
+
@require(lambda concrete_cls_index: concrete_cls_index >= 0)
|
|
1133
|
+
@ensure(lambda result: (result[0] is None) ^ (result[1] is None))
|
|
1134
|
+
def _generate_class(
|
|
1135
|
+
cls: intermediate.ConcreteClass,
|
|
1136
|
+
spec_impls: specific_implementations.SpecificImplementations,
|
|
1137
|
+
concrete_cls_index: int,
|
|
1138
|
+
) -> Tuple[Optional[Stripped], Optional[Error]]:
|
|
1139
|
+
"""
|
|
1140
|
+
Generate TypeScript code for the given concrete class ``cls``.
|
|
1141
|
+
|
|
1142
|
+
``concrete_cls_index`` refers to the number of the concrete class in
|
|
1143
|
+
the ``concrete_classes`` of the symbol table.
|
|
1144
|
+
"""
|
|
1145
|
+
# NOTE (mristin):
|
|
1146
|
+
# Code blocks of the class body separated by double newlines and indented once.
|
|
1147
|
+
|
|
1148
|
+
model_type_enum = typescript_naming.enum_name(Identifier("Model_type"))
|
|
1149
|
+
model_type_getter = typescript_naming.method_name(Identifier("model_type"))
|
|
1150
|
+
|
|
1151
|
+
model_type_literal = typescript_naming.enum_literal_name(Identifier(cls.name))
|
|
1152
|
+
|
|
1153
|
+
blocks = [
|
|
1154
|
+
Stripped(
|
|
1155
|
+
f"""\
|
|
1156
|
+
/**
|
|
1157
|
+
* Indicate the runtime model type of the instance.
|
|
1158
|
+
*/
|
|
1159
|
+
{model_type_getter}(): {model_type_enum} {{
|
|
1160
|
+
{I}// NOTE (mristin, 2022-12-03):
|
|
1161
|
+
{I}// We yield numbers instead of literals to avoid name lookups on platforms
|
|
1162
|
+
{I}// which do not provide JIT compilation of hot paths.
|
|
1163
|
+
{I}return <{model_type_enum}>{concrete_cls_index}; // {model_type_literal}
|
|
1164
|
+
}}"""
|
|
1165
|
+
)
|
|
1166
|
+
] # type: List[Stripped]
|
|
1167
|
+
|
|
1168
|
+
# region Property definitions
|
|
1169
|
+
|
|
1170
|
+
for prop in cls.properties:
|
|
1171
|
+
prop_comment = None # type: Optional[Stripped]
|
|
1172
|
+
if prop.description is not None:
|
|
1173
|
+
prop_comment, prop_comment_errors = _generate_comment_for_property(
|
|
1174
|
+
cls=cls, prop=prop
|
|
1175
|
+
)
|
|
1176
|
+
if prop_comment_errors is not None:
|
|
1177
|
+
return None, Error(
|
|
1178
|
+
prop.description.parsed.node,
|
|
1179
|
+
"Failed to generate the property comment",
|
|
1180
|
+
prop_comment_errors,
|
|
1181
|
+
)
|
|
1182
|
+
else:
|
|
1183
|
+
assert prop_comment is not None
|
|
1184
|
+
|
|
1185
|
+
prop_type = typescript_common.generate_type(
|
|
1186
|
+
type_annotation=prop.type_annotation
|
|
1187
|
+
)
|
|
1188
|
+
prop_name = typescript_naming.property_name(prop.name)
|
|
1189
|
+
|
|
1190
|
+
writer = io.StringIO()
|
|
1191
|
+
if prop_comment is not None:
|
|
1192
|
+
writer.write(prop_comment)
|
|
1193
|
+
writer.write("\n")
|
|
1194
|
+
writer.write(f"{prop_name}: {prop_type};")
|
|
1195
|
+
blocks.append(Stripped(writer.getvalue()))
|
|
1196
|
+
|
|
1197
|
+
# endregion
|
|
1198
|
+
|
|
1199
|
+
# region over_X_or_empty getter
|
|
1200
|
+
|
|
1201
|
+
for prop in cls.properties:
|
|
1202
|
+
if isinstance(
|
|
1203
|
+
prop.type_annotation, intermediate.OptionalTypeAnnotation
|
|
1204
|
+
) and isinstance(prop.type_annotation.value, intermediate.ListTypeAnnotation):
|
|
1205
|
+
prop_name = typescript_naming.property_name(prop.name)
|
|
1206
|
+
items_type = typescript_common.generate_type(
|
|
1207
|
+
prop.type_annotation.value.items
|
|
1208
|
+
)
|
|
1209
|
+
|
|
1210
|
+
over_x_or_empty = typescript_naming.method_name(
|
|
1211
|
+
Identifier(f"over_{prop.name}_or_empty")
|
|
1212
|
+
)
|
|
1213
|
+
|
|
1214
|
+
blocks.append(
|
|
1215
|
+
Stripped(
|
|
1216
|
+
f"""\
|
|
1217
|
+
/**
|
|
1218
|
+
* Yield from {{@link {prop_name}}} if it is set, or yield nothing.
|
|
1219
|
+
*/
|
|
1220
|
+
*{over_x_or_empty}(): IterableIterator<{items_type}> {{
|
|
1221
|
+
{I}if (this.{prop_name} !== null) {{
|
|
1222
|
+
{II}yield * this.{prop_name};
|
|
1223
|
+
{I}}}
|
|
1224
|
+
{I}return;
|
|
1225
|
+
}}"""
|
|
1226
|
+
)
|
|
1227
|
+
)
|
|
1228
|
+
|
|
1229
|
+
# endregion
|
|
1230
|
+
|
|
1231
|
+
# region Methods
|
|
1232
|
+
|
|
1233
|
+
errors = [] # type: List[Error]
|
|
1234
|
+
|
|
1235
|
+
for method in cls.methods:
|
|
1236
|
+
if isinstance(method, intermediate.ImplementationSpecificMethod):
|
|
1237
|
+
implementation_key = specific_implementations.ImplementationKey(
|
|
1238
|
+
f"Types/{method.specified_for.name}/{method.name}.ts"
|
|
1239
|
+
)
|
|
1240
|
+
|
|
1241
|
+
implementation = spec_impls.get(implementation_key, None)
|
|
1242
|
+
|
|
1243
|
+
if implementation is None:
|
|
1244
|
+
errors.append(
|
|
1245
|
+
Error(
|
|
1246
|
+
method.parsed.node,
|
|
1247
|
+
f"The implementation is missing for "
|
|
1248
|
+
f"the implementation-specific method: {implementation_key}",
|
|
1249
|
+
)
|
|
1250
|
+
)
|
|
1251
|
+
continue
|
|
1252
|
+
|
|
1253
|
+
blocks.append(implementation)
|
|
1254
|
+
else:
|
|
1255
|
+
errors.append(
|
|
1256
|
+
Error(
|
|
1257
|
+
cls.parsed.node,
|
|
1258
|
+
"(mristin, 2022-11-10) "
|
|
1259
|
+
"At the moment, we do not transpile the method body and "
|
|
1260
|
+
"its contracts. We want to finish the meta-model for the V3, "
|
|
1261
|
+
"fix de/serialization and generate SDKs for a couple of languages "
|
|
1262
|
+
"before taking on this rather hard task.",
|
|
1263
|
+
)
|
|
1264
|
+
)
|
|
1265
|
+
|
|
1266
|
+
blocks.append(_generate_descend_once_method(cls=cls))
|
|
1267
|
+
|
|
1268
|
+
blocks.append(_generate_descend_method(cls=cls))
|
|
1269
|
+
|
|
1270
|
+
visit_name = typescript_naming.method_name(Identifier(f"visit_{cls.name}"))
|
|
1271
|
+
|
|
1272
|
+
blocks.append(
|
|
1273
|
+
Stripped(
|
|
1274
|
+
f"""\
|
|
1275
|
+
/**
|
|
1276
|
+
* Dispatch `visitor` on this instance.
|
|
1277
|
+
*
|
|
1278
|
+
* @param visitor - to visit this instance
|
|
1279
|
+
*/
|
|
1280
|
+
accept(visitor: AbstractVisitor): void {{
|
|
1281
|
+
{I}visitor.{visit_name}(this);
|
|
1282
|
+
}}"""
|
|
1283
|
+
)
|
|
1284
|
+
)
|
|
1285
|
+
|
|
1286
|
+
visit_with_context_name = typescript_naming.method_name(
|
|
1287
|
+
Identifier(f"visit_{cls.name}_with_context")
|
|
1288
|
+
)
|
|
1289
|
+
|
|
1290
|
+
blocks.append(
|
|
1291
|
+
Stripped(
|
|
1292
|
+
f"""\
|
|
1293
|
+
/**
|
|
1294
|
+
* Dispatch `visitor` with `context` on this instance.
|
|
1295
|
+
*
|
|
1296
|
+
* @param visitor - to visit this instance
|
|
1297
|
+
* @param context - to be passed along to the dispatched visitor method
|
|
1298
|
+
* @typeParam ContextT - type of the context
|
|
1299
|
+
*/
|
|
1300
|
+
acceptWithContext<ContextT>(
|
|
1301
|
+
{I}visitor: AbstractVisitorWithContext<ContextT>,
|
|
1302
|
+
{I}context: ContextT
|
|
1303
|
+
) {{
|
|
1304
|
+
{I}visitor.{visit_with_context_name}(this, context);
|
|
1305
|
+
}}"""
|
|
1306
|
+
)
|
|
1307
|
+
)
|
|
1308
|
+
|
|
1309
|
+
transform_name = typescript_naming.method_name(Identifier(f"transform_{cls.name}"))
|
|
1310
|
+
|
|
1311
|
+
blocks.append(
|
|
1312
|
+
Stripped(
|
|
1313
|
+
f"""\
|
|
1314
|
+
/**
|
|
1315
|
+
* Dispatch the `transformer` on this instance.
|
|
1316
|
+
*
|
|
1317
|
+
* @param transformer - to transform this instance
|
|
1318
|
+
* @returns transformation of this instance
|
|
1319
|
+
* @paramType T - type of the transformation result
|
|
1320
|
+
*/
|
|
1321
|
+
transform<T>(transformer: AbstractTransformer<T>): T {{
|
|
1322
|
+
{I}return transformer.{transform_name}(this);
|
|
1323
|
+
}}"""
|
|
1324
|
+
)
|
|
1325
|
+
)
|
|
1326
|
+
|
|
1327
|
+
transform_with_context_name = typescript_naming.method_name(
|
|
1328
|
+
Identifier(f"transform_{cls.name}_with_context")
|
|
1329
|
+
)
|
|
1330
|
+
|
|
1331
|
+
blocks.append(
|
|
1332
|
+
Stripped(
|
|
1333
|
+
f"""\
|
|
1334
|
+
/**
|
|
1335
|
+
* Dispatch the `transformer` on this instance in `context`.
|
|
1336
|
+
*
|
|
1337
|
+
* @param transformer - to transform this instance
|
|
1338
|
+
* @param context - to be passed along to the `transformer`
|
|
1339
|
+
* @returns transformation of this instance
|
|
1340
|
+
* @paramType T - type of the transformation result
|
|
1341
|
+
* @paramType ContextT - type of the transformation context
|
|
1342
|
+
*/
|
|
1343
|
+
transformWithContext<ContextT, T>(
|
|
1344
|
+
{I}transformer: AbstractTransformerWithContext<ContextT, T>,
|
|
1345
|
+
{I}context: ContextT
|
|
1346
|
+
): T {{
|
|
1347
|
+
{I}return transformer.{transform_with_context_name}(
|
|
1348
|
+
{II}this, context
|
|
1349
|
+
{I});
|
|
1350
|
+
}}"""
|
|
1351
|
+
)
|
|
1352
|
+
)
|
|
1353
|
+
|
|
1354
|
+
# endregion
|
|
1355
|
+
|
|
1356
|
+
# region Constructor
|
|
1357
|
+
|
|
1358
|
+
if cls.constructor.is_implementation_specific:
|
|
1359
|
+
implementation_key = specific_implementations.ImplementationKey(
|
|
1360
|
+
f"Types/{cls.name}/{cls.name}.py"
|
|
1361
|
+
)
|
|
1362
|
+
implementation = spec_impls.get(implementation_key, None)
|
|
1363
|
+
|
|
1364
|
+
if implementation is None:
|
|
1365
|
+
errors.append(
|
|
1366
|
+
Error(
|
|
1367
|
+
cls.parsed.node,
|
|
1368
|
+
f"The implementation of the implementation-specific constructor "
|
|
1369
|
+
f"is missing: {implementation_key}",
|
|
1370
|
+
)
|
|
1371
|
+
)
|
|
1372
|
+
else:
|
|
1373
|
+
blocks.append(implementation)
|
|
1374
|
+
else:
|
|
1375
|
+
constructor_block, error = _generate_constructor(cls=cls)
|
|
1376
|
+
|
|
1377
|
+
if error is not None:
|
|
1378
|
+
errors.append(error)
|
|
1379
|
+
else:
|
|
1380
|
+
assert constructor_block is not None
|
|
1381
|
+
|
|
1382
|
+
# NOTE (mristin, 2022-06-21):
|
|
1383
|
+
# Empty constructor will be automatically generated by the interpreter.
|
|
1384
|
+
if constructor_block != "":
|
|
1385
|
+
blocks.append(constructor_block)
|
|
1386
|
+
|
|
1387
|
+
# endregion
|
|
1388
|
+
|
|
1389
|
+
if len(errors) > 0:
|
|
1390
|
+
return None, Error(
|
|
1391
|
+
cls.parsed.node,
|
|
1392
|
+
f"Failed to generate the code for the class {cls.name}",
|
|
1393
|
+
errors,
|
|
1394
|
+
)
|
|
1395
|
+
|
|
1396
|
+
if len(blocks) == 0:
|
|
1397
|
+
blocks = [Stripped("// Intentionally empty.")]
|
|
1398
|
+
|
|
1399
|
+
# region Description
|
|
1400
|
+
|
|
1401
|
+
comment = None # type: Optional[Stripped]
|
|
1402
|
+
if cls.description is not None:
|
|
1403
|
+
comment, comment_errors = _generate_comment_for_cls_or_enum(cls_or_enum=cls)
|
|
1404
|
+
if comment_errors is not None:
|
|
1405
|
+
return None, Error(
|
|
1406
|
+
cls.description.parsed.node,
|
|
1407
|
+
f"Failed to generate the documentation comment for class {cls.name!r}",
|
|
1408
|
+
comment_errors,
|
|
1409
|
+
)
|
|
1410
|
+
|
|
1411
|
+
assert comment is not None
|
|
1412
|
+
|
|
1413
|
+
# endregion
|
|
1414
|
+
|
|
1415
|
+
# region Implements
|
|
1416
|
+
|
|
1417
|
+
# NOTE (mristin, 2022-12-14):
|
|
1418
|
+
# Since JavaScript and hence TypeScript do not support multiple inheritance, we
|
|
1419
|
+
# model all the abstract classes as interfaces. Our class therefore extends only
|
|
1420
|
+
# the most general class ``Class``, but implements all the corresponding interfaces.
|
|
1421
|
+
#
|
|
1422
|
+
# Interfaces are only descriptive in TypeScript, so we can not use them directly
|
|
1423
|
+
# for efficient type switching at runtime. To implement type switches, we rely
|
|
1424
|
+
# on transformer pattern, where we generate the corresponding type-switching
|
|
1425
|
+
# transformers. See ``AS_*_TRANSFORMER``'s.
|
|
1426
|
+
|
|
1427
|
+
interface_names = [] # type: List[Identifier]
|
|
1428
|
+
|
|
1429
|
+
if len(cls.concrete_descendants) > 0:
|
|
1430
|
+
# NOTE (mristin, 2022-12-14):
|
|
1431
|
+
# We do not have to add any other interfaces, as the interface corresponding
|
|
1432
|
+
# to this concrete class will already entail all the antecedents.
|
|
1433
|
+
|
|
1434
|
+
assert cls.interface is not None, (
|
|
1435
|
+
f"Expected interface for the class {cls.name!r} "
|
|
1436
|
+
f"as it has concrete descendants"
|
|
1437
|
+
)
|
|
1438
|
+
|
|
1439
|
+
interface_names.append(typescript_naming.interface_name(cls.name))
|
|
1440
|
+
else:
|
|
1441
|
+
for inheritance in cls.inheritances:
|
|
1442
|
+
assert inheritance.interface is not None, (
|
|
1443
|
+
f"Expected interface in the parent class {inheritance.name!r} "
|
|
1444
|
+
f"of class {cls.name!r}"
|
|
1445
|
+
)
|
|
1446
|
+
|
|
1447
|
+
interface_names.append(
|
|
1448
|
+
typescript_naming.interface_name(inheritance.interface.name)
|
|
1449
|
+
)
|
|
1450
|
+
|
|
1451
|
+
# endregion
|
|
1452
|
+
|
|
1453
|
+
writer = io.StringIO()
|
|
1454
|
+
if comment is not None:
|
|
1455
|
+
writer.write(comment)
|
|
1456
|
+
writer.write("\n")
|
|
1457
|
+
|
|
1458
|
+
name = typescript_naming.class_name(cls.name)
|
|
1459
|
+
|
|
1460
|
+
if len(interface_names) == 0:
|
|
1461
|
+
writer.write(
|
|
1462
|
+
f"""\
|
|
1463
|
+
export class {name} extends Class {{
|
|
1464
|
+
"""
|
|
1465
|
+
)
|
|
1466
|
+
else:
|
|
1467
|
+
interface_names_joined = ",\n".join(interface_names)
|
|
1468
|
+
writer.write(
|
|
1469
|
+
f"""\
|
|
1470
|
+
export class {name}
|
|
1471
|
+
{I}extends Class
|
|
1472
|
+
{I}implements {indent_but_first_line(interface_names_joined, I)} {{
|
|
1473
|
+
"""
|
|
1474
|
+
)
|
|
1475
|
+
|
|
1476
|
+
for i, block in enumerate(blocks):
|
|
1477
|
+
if i > 0:
|
|
1478
|
+
writer.write("\n\n")
|
|
1479
|
+
writer.write(textwrap.indent(block, I))
|
|
1480
|
+
|
|
1481
|
+
writer.write("\n}")
|
|
1482
|
+
|
|
1483
|
+
return Stripped(writer.getvalue()), None
|
|
1484
|
+
|
|
1485
|
+
|
|
1486
|
+
def _generate_abstract_visitor(symbol_table: intermediate.SymbolTable) -> Stripped:
|
|
1487
|
+
"""Generate the code for the abstract visitor."""
|
|
1488
|
+
blocks = [
|
|
1489
|
+
Stripped(
|
|
1490
|
+
f"""\
|
|
1491
|
+
/**
|
|
1492
|
+
* Double-dispatch on `that`.
|
|
1493
|
+
*/
|
|
1494
|
+
visit(that: Class): void {{
|
|
1495
|
+
{I}that.accept(this);
|
|
1496
|
+
}}"""
|
|
1497
|
+
)
|
|
1498
|
+
] # type: List[Stripped]
|
|
1499
|
+
|
|
1500
|
+
for cls in symbol_table.concrete_classes:
|
|
1501
|
+
visit_name = typescript_naming.method_name(Identifier(f"visit_{cls.name}"))
|
|
1502
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
1503
|
+
|
|
1504
|
+
blocks.append(
|
|
1505
|
+
Stripped(
|
|
1506
|
+
f"""\
|
|
1507
|
+
/**
|
|
1508
|
+
* Visit `that`.
|
|
1509
|
+
*
|
|
1510
|
+
* @param that - instance to be visited
|
|
1511
|
+
*/
|
|
1512
|
+
abstract {visit_name}(
|
|
1513
|
+
{I}that: {cls_name}
|
|
1514
|
+
): void;"""
|
|
1515
|
+
)
|
|
1516
|
+
)
|
|
1517
|
+
|
|
1518
|
+
writer = io.StringIO()
|
|
1519
|
+
writer.write(
|
|
1520
|
+
"""\
|
|
1521
|
+
/**
|
|
1522
|
+
* Visit the instances of the model.
|
|
1523
|
+
*/
|
|
1524
|
+
export abstract class AbstractVisitor {
|
|
1525
|
+
"""
|
|
1526
|
+
)
|
|
1527
|
+
|
|
1528
|
+
for i, block in enumerate(blocks):
|
|
1529
|
+
if i > 0:
|
|
1530
|
+
writer.write("\n\n")
|
|
1531
|
+
|
|
1532
|
+
writer.write(textwrap.indent(block, I))
|
|
1533
|
+
|
|
1534
|
+
writer.write("\n}")
|
|
1535
|
+
|
|
1536
|
+
return Stripped(writer.getvalue())
|
|
1537
|
+
|
|
1538
|
+
|
|
1539
|
+
def _generate_abstract_visitor_with_context(
|
|
1540
|
+
symbol_table: intermediate.SymbolTable,
|
|
1541
|
+
) -> Stripped:
|
|
1542
|
+
"""Generate the code for the abstract visitor with context."""
|
|
1543
|
+
blocks = [
|
|
1544
|
+
Stripped(
|
|
1545
|
+
f"""\
|
|
1546
|
+
/**
|
|
1547
|
+
* Double-dispatch on `that` in `context`.
|
|
1548
|
+
*
|
|
1549
|
+
* @param that - instance to be visited
|
|
1550
|
+
* @param context - of the visitation
|
|
1551
|
+
*/
|
|
1552
|
+
visitWithContext(
|
|
1553
|
+
{I}that: Class,
|
|
1554
|
+
{I}context: ContextT
|
|
1555
|
+
): void {{
|
|
1556
|
+
{I}that.acceptWithContext(this, context);
|
|
1557
|
+
}}"""
|
|
1558
|
+
)
|
|
1559
|
+
] # type: List[Stripped]
|
|
1560
|
+
|
|
1561
|
+
for cls in symbol_table.concrete_classes:
|
|
1562
|
+
visit_with_context_name = typescript_naming.method_name(
|
|
1563
|
+
Identifier(f"visit_{cls.name}_with_context")
|
|
1564
|
+
)
|
|
1565
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
1566
|
+
|
|
1567
|
+
blocks.append(
|
|
1568
|
+
Stripped(
|
|
1569
|
+
f"""\
|
|
1570
|
+
/**
|
|
1571
|
+
* Visit `that` in `context`.
|
|
1572
|
+
*
|
|
1573
|
+
* @param that - instance to be visited
|
|
1574
|
+
* @param context - of the visitation
|
|
1575
|
+
*/
|
|
1576
|
+
abstract {visit_with_context_name}(
|
|
1577
|
+
{I}that: {cls_name},
|
|
1578
|
+
{I}context: ContextT
|
|
1579
|
+
): void;"""
|
|
1580
|
+
)
|
|
1581
|
+
)
|
|
1582
|
+
|
|
1583
|
+
writer = io.StringIO()
|
|
1584
|
+
writer.write(
|
|
1585
|
+
"""\
|
|
1586
|
+
/**
|
|
1587
|
+
* Visit the instances of the model with context.
|
|
1588
|
+
*
|
|
1589
|
+
* @typeParam ContextT - type of the visitation context
|
|
1590
|
+
*/
|
|
1591
|
+
export abstract class AbstractVisitorWithContext<ContextT> {
|
|
1592
|
+
"""
|
|
1593
|
+
)
|
|
1594
|
+
|
|
1595
|
+
for i, block in enumerate(blocks):
|
|
1596
|
+
if i > 0:
|
|
1597
|
+
writer.write("\n\n")
|
|
1598
|
+
|
|
1599
|
+
writer.write(textwrap.indent(block, I))
|
|
1600
|
+
|
|
1601
|
+
writer.write("\n}")
|
|
1602
|
+
|
|
1603
|
+
return Stripped(writer.getvalue())
|
|
1604
|
+
|
|
1605
|
+
|
|
1606
|
+
def _generate_pass_through_visitor(symbol_table: intermediate.SymbolTable) -> Stripped:
|
|
1607
|
+
"""Generate the code for the pass-through visitor."""
|
|
1608
|
+
blocks = [] # type: List[Stripped]
|
|
1609
|
+
|
|
1610
|
+
for cls in symbol_table.concrete_classes:
|
|
1611
|
+
visit_name = typescript_naming.method_name(Identifier(f"visit_{cls.name}"))
|
|
1612
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
1613
|
+
|
|
1614
|
+
blocks.append(
|
|
1615
|
+
Stripped(
|
|
1616
|
+
f"""\
|
|
1617
|
+
/**
|
|
1618
|
+
* Visit `that`.
|
|
1619
|
+
*
|
|
1620
|
+
* @param that - instance to be visited
|
|
1621
|
+
*/
|
|
1622
|
+
{visit_name}(
|
|
1623
|
+
{I}that: {cls_name}
|
|
1624
|
+
): void {{
|
|
1625
|
+
{I}for (const another of that.descendOnce()) {{
|
|
1626
|
+
{II}this.visit(another);
|
|
1627
|
+
{I}}}
|
|
1628
|
+
}}"""
|
|
1629
|
+
)
|
|
1630
|
+
)
|
|
1631
|
+
|
|
1632
|
+
writer = io.StringIO()
|
|
1633
|
+
writer.write(
|
|
1634
|
+
"""\
|
|
1635
|
+
/**
|
|
1636
|
+
* Visit the instances of the model without action.
|
|
1637
|
+
*
|
|
1638
|
+
* @remarks
|
|
1639
|
+
* This visitor is not meant to be directly used. Instead, you usually
|
|
1640
|
+
* inherit from it, and implement only the relevant visit methods.
|
|
1641
|
+
*/
|
|
1642
|
+
export class PassThroughVisitor extends AbstractVisitor {
|
|
1643
|
+
"""
|
|
1644
|
+
)
|
|
1645
|
+
|
|
1646
|
+
for i, block in enumerate(blocks):
|
|
1647
|
+
if i > 0:
|
|
1648
|
+
writer.write("\n\n")
|
|
1649
|
+
|
|
1650
|
+
writer.write(textwrap.indent(block, I))
|
|
1651
|
+
|
|
1652
|
+
writer.write("\n}")
|
|
1653
|
+
|
|
1654
|
+
return Stripped(writer.getvalue())
|
|
1655
|
+
|
|
1656
|
+
|
|
1657
|
+
def _generate_pass_through_visitor_with_context(
|
|
1658
|
+
symbol_table: intermediate.SymbolTable,
|
|
1659
|
+
) -> Stripped:
|
|
1660
|
+
"""Generate the code for the pass-through visitor with context."""
|
|
1661
|
+
blocks = [
|
|
1662
|
+
Stripped(
|
|
1663
|
+
f"""\
|
|
1664
|
+
/**
|
|
1665
|
+
* Double-dispatch on `that` in `context`.
|
|
1666
|
+
*/
|
|
1667
|
+
visitWithContext(
|
|
1668
|
+
{I}that: Class,
|
|
1669
|
+
{I}context: ContextT
|
|
1670
|
+
): void {{
|
|
1671
|
+
{I}that.acceptWithContext(this, context);
|
|
1672
|
+
}}"""
|
|
1673
|
+
)
|
|
1674
|
+
] # type: List[Stripped]
|
|
1675
|
+
|
|
1676
|
+
for cls in symbol_table.concrete_classes:
|
|
1677
|
+
visit_with_context_name = typescript_naming.method_name(
|
|
1678
|
+
Identifier(f"visit_{cls.name}_with_context")
|
|
1679
|
+
)
|
|
1680
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
1681
|
+
|
|
1682
|
+
blocks.append(
|
|
1683
|
+
Stripped(
|
|
1684
|
+
f"""\
|
|
1685
|
+
/**
|
|
1686
|
+
* Visit `that` in `context`.
|
|
1687
|
+
*
|
|
1688
|
+
* @param that - instance to be visited
|
|
1689
|
+
* @param context - of the visitation
|
|
1690
|
+
*/
|
|
1691
|
+
{visit_with_context_name}(
|
|
1692
|
+
{I}that: {cls_name},
|
|
1693
|
+
{I}context: ContextT
|
|
1694
|
+
): void {{
|
|
1695
|
+
{I}for (const another of that.descendOnce()) {{
|
|
1696
|
+
{II}this.visitWithContext(another, context);
|
|
1697
|
+
{I}}}
|
|
1698
|
+
}}"""
|
|
1699
|
+
)
|
|
1700
|
+
)
|
|
1701
|
+
|
|
1702
|
+
writer = io.StringIO()
|
|
1703
|
+
writer.write(
|
|
1704
|
+
f"""\
|
|
1705
|
+
/**
|
|
1706
|
+
* Visit the instances of the model without action and in context.
|
|
1707
|
+
*
|
|
1708
|
+
* @remarks
|
|
1709
|
+
* This visitor is not meant to be directly used. Instead, you usually
|
|
1710
|
+
* inherit from it, and implement only the relevant visit methods.
|
|
1711
|
+
*/
|
|
1712
|
+
export class PassThroughVisitorWithContext<ContextT>
|
|
1713
|
+
{II}extends AbstractVisitorWithContext<ContextT> {{
|
|
1714
|
+
"""
|
|
1715
|
+
)
|
|
1716
|
+
|
|
1717
|
+
for i, block in enumerate(blocks):
|
|
1718
|
+
if i > 0:
|
|
1719
|
+
writer.write("\n\n")
|
|
1720
|
+
|
|
1721
|
+
writer.write(textwrap.indent(block, I))
|
|
1722
|
+
|
|
1723
|
+
writer.write("\n}")
|
|
1724
|
+
|
|
1725
|
+
return Stripped(writer.getvalue())
|
|
1726
|
+
|
|
1727
|
+
|
|
1728
|
+
def _generate_abstract_transformer(symbol_table: intermediate.SymbolTable) -> Stripped:
|
|
1729
|
+
"""Generate the code for the abstract transformer."""
|
|
1730
|
+
blocks = [
|
|
1731
|
+
Stripped(
|
|
1732
|
+
f"""\
|
|
1733
|
+
/**
|
|
1734
|
+
* Double-dispatch on `that`.
|
|
1735
|
+
*/
|
|
1736
|
+
transform(that: Class): T {{
|
|
1737
|
+
{I}return that.transform(this);
|
|
1738
|
+
}}"""
|
|
1739
|
+
)
|
|
1740
|
+
] # type: List[Stripped]
|
|
1741
|
+
|
|
1742
|
+
for cls in symbol_table.concrete_classes:
|
|
1743
|
+
transform_name = typescript_naming.method_name(
|
|
1744
|
+
Identifier(f"transform_{cls.name}")
|
|
1745
|
+
)
|
|
1746
|
+
|
|
1747
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
1748
|
+
|
|
1749
|
+
blocks.append(
|
|
1750
|
+
Stripped(
|
|
1751
|
+
f"""\
|
|
1752
|
+
/**
|
|
1753
|
+
* Transform `that`.
|
|
1754
|
+
*
|
|
1755
|
+
* @param that - instance to be transformed
|
|
1756
|
+
* @returns transformed `that`
|
|
1757
|
+
*/
|
|
1758
|
+
abstract {transform_name}(
|
|
1759
|
+
{I}that: {cls_name}
|
|
1760
|
+
): T;"""
|
|
1761
|
+
)
|
|
1762
|
+
)
|
|
1763
|
+
|
|
1764
|
+
writer = io.StringIO()
|
|
1765
|
+
writer.write(
|
|
1766
|
+
"""\
|
|
1767
|
+
/**
|
|
1768
|
+
* Transform the instance of the model.
|
|
1769
|
+
*
|
|
1770
|
+
* @typeParam T - type of the transformation result
|
|
1771
|
+
*/
|
|
1772
|
+
export abstract class AbstractTransformer<T> {
|
|
1773
|
+
"""
|
|
1774
|
+
)
|
|
1775
|
+
|
|
1776
|
+
for i, block in enumerate(blocks):
|
|
1777
|
+
if i > 0:
|
|
1778
|
+
writer.write("\n\n")
|
|
1779
|
+
|
|
1780
|
+
writer.write(textwrap.indent(block, I))
|
|
1781
|
+
|
|
1782
|
+
writer.write("\n}")
|
|
1783
|
+
|
|
1784
|
+
return Stripped(writer.getvalue())
|
|
1785
|
+
|
|
1786
|
+
|
|
1787
|
+
def _generate_abstract_transformer_with_context(
|
|
1788
|
+
symbol_table: intermediate.SymbolTable,
|
|
1789
|
+
) -> Stripped:
|
|
1790
|
+
"""Generate the code for the abstract transformer with context."""
|
|
1791
|
+
blocks = [
|
|
1792
|
+
Stripped(
|
|
1793
|
+
f"""\
|
|
1794
|
+
/**
|
|
1795
|
+
* Double-dispatch on `that` in `context`.
|
|
1796
|
+
*
|
|
1797
|
+
* @param that - instance to be transformed
|
|
1798
|
+
* @param context - of the transformation
|
|
1799
|
+
* @returns transformed `that`
|
|
1800
|
+
*/
|
|
1801
|
+
transformWithContext(
|
|
1802
|
+
{I}that: Class,
|
|
1803
|
+
{I}context: ContextT
|
|
1804
|
+
): T {{
|
|
1805
|
+
{I}return that.transformWithContext(this, context);
|
|
1806
|
+
}}"""
|
|
1807
|
+
)
|
|
1808
|
+
] # type: List[Stripped]
|
|
1809
|
+
|
|
1810
|
+
for cls in symbol_table.concrete_classes:
|
|
1811
|
+
transform_with_context_name = typescript_naming.method_name(
|
|
1812
|
+
Identifier(f"transform_{cls.name}_with_context")
|
|
1813
|
+
)
|
|
1814
|
+
|
|
1815
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
1816
|
+
|
|
1817
|
+
blocks.append(
|
|
1818
|
+
Stripped(
|
|
1819
|
+
f"""\
|
|
1820
|
+
/**
|
|
1821
|
+
* Transform `that` in `context`.
|
|
1822
|
+
*
|
|
1823
|
+
* @param that - instance to be transformed
|
|
1824
|
+
* @param context - of the transformation
|
|
1825
|
+
* @returns transformed `that`
|
|
1826
|
+
*/
|
|
1827
|
+
abstract {transform_with_context_name}(
|
|
1828
|
+
{I}that: {cls_name},
|
|
1829
|
+
{I}context: ContextT
|
|
1830
|
+
): T;"""
|
|
1831
|
+
)
|
|
1832
|
+
)
|
|
1833
|
+
|
|
1834
|
+
writer = io.StringIO()
|
|
1835
|
+
writer.write(
|
|
1836
|
+
"""\
|
|
1837
|
+
/**
|
|
1838
|
+
* Transform the instances of the model in context.
|
|
1839
|
+
*
|
|
1840
|
+
* @typeParam ContextT - type of the transformation context
|
|
1841
|
+
* @typeParam T - type of the transformation result
|
|
1842
|
+
*/
|
|
1843
|
+
export abstract class AbstractTransformerWithContext<ContextT, T> {
|
|
1844
|
+
"""
|
|
1845
|
+
)
|
|
1846
|
+
|
|
1847
|
+
for i, block in enumerate(blocks):
|
|
1848
|
+
if i > 0:
|
|
1849
|
+
writer.write("\n\n")
|
|
1850
|
+
|
|
1851
|
+
writer.write(textwrap.indent(block, I))
|
|
1852
|
+
|
|
1853
|
+
writer.write("\n}")
|
|
1854
|
+
|
|
1855
|
+
return Stripped(writer.getvalue())
|
|
1856
|
+
|
|
1857
|
+
|
|
1858
|
+
def _generate_transformer_with_default(
|
|
1859
|
+
symbol_table: intermediate.SymbolTable,
|
|
1860
|
+
) -> Stripped:
|
|
1861
|
+
"""Generate the code for the transformer with default transformation."""
|
|
1862
|
+
blocks = [
|
|
1863
|
+
Stripped(
|
|
1864
|
+
"""\
|
|
1865
|
+
/**
|
|
1866
|
+
* Default value which is returned if no override of the transformation
|
|
1867
|
+
*/
|
|
1868
|
+
defaultResult: T"""
|
|
1869
|
+
),
|
|
1870
|
+
Stripped(
|
|
1871
|
+
f"""\
|
|
1872
|
+
/**
|
|
1873
|
+
* Initialize with the given `default` value.
|
|
1874
|
+
*
|
|
1875
|
+
* @param defaultResult - returned if no override of the transformation
|
|
1876
|
+
*/
|
|
1877
|
+
constructor(defaultResult: T) {{
|
|
1878
|
+
{I}super();
|
|
1879
|
+
{I}this.defaultResult = defaultResult;
|
|
1880
|
+
}}"""
|
|
1881
|
+
),
|
|
1882
|
+
] # type: List[Stripped]
|
|
1883
|
+
|
|
1884
|
+
for cls in symbol_table.concrete_classes:
|
|
1885
|
+
transform_name = typescript_naming.method_name(
|
|
1886
|
+
Identifier(f"transform_{cls.name}")
|
|
1887
|
+
)
|
|
1888
|
+
|
|
1889
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
1890
|
+
|
|
1891
|
+
blocks.append(
|
|
1892
|
+
Stripped(
|
|
1893
|
+
f"""\
|
|
1894
|
+
/**
|
|
1895
|
+
* Transform `that`.
|
|
1896
|
+
*
|
|
1897
|
+
* @param that - instance to be transformed
|
|
1898
|
+
* @returns transformed `that`
|
|
1899
|
+
*/
|
|
1900
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
1901
|
+
{transform_name}(
|
|
1902
|
+
{I}that: {cls_name}
|
|
1903
|
+
): T {{
|
|
1904
|
+
{I}return this.defaultResult;
|
|
1905
|
+
}}
|
|
1906
|
+
/* eslint-enable @typescript-eslint/no-unused-vars */"""
|
|
1907
|
+
)
|
|
1908
|
+
)
|
|
1909
|
+
|
|
1910
|
+
writer = io.StringIO()
|
|
1911
|
+
writer.write(
|
|
1912
|
+
"""\
|
|
1913
|
+
/**
|
|
1914
|
+
* Transform the instances of the model.
|
|
1915
|
+
*
|
|
1916
|
+
* @remarks
|
|
1917
|
+
* If you do not override the transformation methods, they simply
|
|
1918
|
+
* return {@link defaultResult}.
|
|
1919
|
+
*
|
|
1920
|
+
* @typeParam T - type of the transformation result
|
|
1921
|
+
*/
|
|
1922
|
+
export class TransformerWithDefault<T> extends AbstractTransformer<T> {
|
|
1923
|
+
"""
|
|
1924
|
+
)
|
|
1925
|
+
|
|
1926
|
+
for i, block in enumerate(blocks):
|
|
1927
|
+
if i > 0:
|
|
1928
|
+
writer.write("\n\n")
|
|
1929
|
+
|
|
1930
|
+
writer.write(textwrap.indent(block, I))
|
|
1931
|
+
|
|
1932
|
+
writer.write("\n}")
|
|
1933
|
+
|
|
1934
|
+
return Stripped(writer.getvalue())
|
|
1935
|
+
|
|
1936
|
+
|
|
1937
|
+
def _generate_transformer_with_default_and_context(
|
|
1938
|
+
symbol_table: intermediate.SymbolTable,
|
|
1939
|
+
) -> Stripped:
|
|
1940
|
+
"""Generate the code for the transformer with default transformation and context."""
|
|
1941
|
+
blocks = [
|
|
1942
|
+
Stripped(
|
|
1943
|
+
"""\
|
|
1944
|
+
/**
|
|
1945
|
+
* Default value which is returned if no override of the transformation
|
|
1946
|
+
*/
|
|
1947
|
+
defaultResult: T"""
|
|
1948
|
+
),
|
|
1949
|
+
Stripped(
|
|
1950
|
+
f"""\
|
|
1951
|
+
/**
|
|
1952
|
+
* Initialize with the given `default` value.
|
|
1953
|
+
*
|
|
1954
|
+
* @param defaultResult - returned if no override of the transformation
|
|
1955
|
+
*/
|
|
1956
|
+
constructor(defaultResult: T) {{
|
|
1957
|
+
{I}super();
|
|
1958
|
+
{I}this.defaultResult = defaultResult;
|
|
1959
|
+
}}"""
|
|
1960
|
+
),
|
|
1961
|
+
] # type: List[Stripped]
|
|
1962
|
+
|
|
1963
|
+
for cls in symbol_table.concrete_classes:
|
|
1964
|
+
transform_with_context_name = typescript_naming.method_name(
|
|
1965
|
+
Identifier(f"transform_{cls.name}_with_context")
|
|
1966
|
+
)
|
|
1967
|
+
|
|
1968
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
1969
|
+
|
|
1970
|
+
blocks.append(
|
|
1971
|
+
Stripped(
|
|
1972
|
+
f"""\
|
|
1973
|
+
/**
|
|
1974
|
+
* Transform `that` in `context`.
|
|
1975
|
+
*
|
|
1976
|
+
* @param that - instance to be transformed
|
|
1977
|
+
* @param context - of the visitation
|
|
1978
|
+
* @returns transformed `that`
|
|
1979
|
+
*/
|
|
1980
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
1981
|
+
{transform_with_context_name}(
|
|
1982
|
+
{I}that: {cls_name},
|
|
1983
|
+
{I}context: ContextT
|
|
1984
|
+
): T {{
|
|
1985
|
+
{I}return this.defaultResult;
|
|
1986
|
+
}}
|
|
1987
|
+
/* eslint-enable @typescript-eslint/no-unused-vars */"""
|
|
1988
|
+
)
|
|
1989
|
+
)
|
|
1990
|
+
|
|
1991
|
+
writer = io.StringIO()
|
|
1992
|
+
writer.write(
|
|
1993
|
+
f"""\
|
|
1994
|
+
/**
|
|
1995
|
+
* Transform the instances of the model in context.
|
|
1996
|
+
*
|
|
1997
|
+
* @remarks
|
|
1998
|
+
* If you do not override the transformation methods, they simply
|
|
1999
|
+
* return {{@link defaultResult}}.
|
|
2000
|
+
*
|
|
2001
|
+
* @typeParam ContextT - type of the visitation context
|
|
2002
|
+
* @typeParam T - type of the transformation result
|
|
2003
|
+
*/
|
|
2004
|
+
export class TransformerWithDefaultAndContext<ContextT, T>
|
|
2005
|
+
{II}extends AbstractTransformerWithContext<ContextT, T> {{
|
|
2006
|
+
"""
|
|
2007
|
+
)
|
|
2008
|
+
|
|
2009
|
+
for i, block in enumerate(blocks):
|
|
2010
|
+
if i > 0:
|
|
2011
|
+
writer.write("\n\n")
|
|
2012
|
+
|
|
2013
|
+
writer.write(textwrap.indent(block, I))
|
|
2014
|
+
|
|
2015
|
+
writer.write("\n}")
|
|
2016
|
+
|
|
2017
|
+
return Stripped(writer.getvalue())
|
|
2018
|
+
|
|
2019
|
+
|
|
2020
|
+
def _generate_comment_for_meta_model(
|
|
2021
|
+
description: intermediate.DescriptionOfMetaModel,
|
|
2022
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
2023
|
+
"""Generate the docstring for the given meta-model."""
|
|
2024
|
+
# fmt: off
|
|
2025
|
+
comment, errors = (
|
|
2026
|
+
typescript_description
|
|
2027
|
+
.generate_documentation_comment_for_summary_remarks_constraints(
|
|
2028
|
+
description=description,
|
|
2029
|
+
context=typescript_description.Context(
|
|
2030
|
+
module=typescript_common.TYPES_MODULE, cls_or_enum=None
|
|
2031
|
+
)
|
|
2032
|
+
)
|
|
2033
|
+
)
|
|
2034
|
+
# fmt: on
|
|
2035
|
+
|
|
2036
|
+
if errors is not None:
|
|
2037
|
+
return None, errors
|
|
2038
|
+
|
|
2039
|
+
assert comment is not None
|
|
2040
|
+
|
|
2041
|
+
return comment, None
|
|
2042
|
+
|
|
2043
|
+
|
|
2044
|
+
def _generate_as_interface_transformer(
|
|
2045
|
+
interface: intermediate.Interface, symbol_table: intermediate.SymbolTable
|
|
2046
|
+
) -> Stripped:
|
|
2047
|
+
blocks = [] # type: List[Stripped]
|
|
2048
|
+
|
|
2049
|
+
interface_name = typescript_naming.interface_name(interface.name)
|
|
2050
|
+
|
|
2051
|
+
for cls in symbol_table.concrete_classes:
|
|
2052
|
+
transform_name = typescript_naming.method_name(
|
|
2053
|
+
Identifier(f"transform_{cls.name}")
|
|
2054
|
+
)
|
|
2055
|
+
|
|
2056
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
2057
|
+
|
|
2058
|
+
if cls.is_subclass_of(interface.base):
|
|
2059
|
+
blocks.append(
|
|
2060
|
+
Stripped(
|
|
2061
|
+
f"""\
|
|
2062
|
+
{transform_name}(
|
|
2063
|
+
{I}that: {cls_name}
|
|
2064
|
+
): {interface_name} | null {{
|
|
2065
|
+
{I}return that as {interface_name};
|
|
2066
|
+
}}"""
|
|
2067
|
+
)
|
|
2068
|
+
)
|
|
2069
|
+
else:
|
|
2070
|
+
blocks.append(
|
|
2071
|
+
Stripped(
|
|
2072
|
+
f"""\
|
|
2073
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2074
|
+
{transform_name}(
|
|
2075
|
+
{I}that: {cls_name}
|
|
2076
|
+
): {interface_name} | null {{
|
|
2077
|
+
{I}return null;
|
|
2078
|
+
}}
|
|
2079
|
+
/* eslint-enable @typescript-eslint/no-unused-vars */"""
|
|
2080
|
+
)
|
|
2081
|
+
)
|
|
2082
|
+
|
|
2083
|
+
transformer_name = typescript_naming.class_name(
|
|
2084
|
+
Identifier(f"As_{interface.name}_transformer")
|
|
2085
|
+
)
|
|
2086
|
+
|
|
2087
|
+
writer = io.StringIO()
|
|
2088
|
+
writer.write(
|
|
2089
|
+
f"""\
|
|
2090
|
+
/**
|
|
2091
|
+
* Try to cast an instance of the model to {{@link {interface_name}}}.
|
|
2092
|
+
*/
|
|
2093
|
+
class {transformer_name}
|
|
2094
|
+
{II}extends AbstractTransformer<{interface_name} | null> {{
|
|
2095
|
+
"""
|
|
2096
|
+
)
|
|
2097
|
+
|
|
2098
|
+
for i, block in enumerate(blocks):
|
|
2099
|
+
if i > 0:
|
|
2100
|
+
writer.write("\n\n")
|
|
2101
|
+
|
|
2102
|
+
writer.write(textwrap.indent(block, I))
|
|
2103
|
+
|
|
2104
|
+
writer.write("\n}")
|
|
2105
|
+
|
|
2106
|
+
return Stripped(writer.getvalue())
|
|
2107
|
+
|
|
2108
|
+
|
|
2109
|
+
def _generate_type_matcher(symbol_table: intermediate.SymbolTable) -> Stripped:
|
|
2110
|
+
blocks = [] # type: List[Stripped]
|
|
2111
|
+
for cls in symbol_table.concrete_classes:
|
|
2112
|
+
transform_name = typescript_naming.method_name(
|
|
2113
|
+
Identifier(f"transform_{cls.name}_with_context")
|
|
2114
|
+
)
|
|
2115
|
+
|
|
2116
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
2117
|
+
|
|
2118
|
+
is_name = typescript_naming.function_name(Identifier(f"is_{cls.name}"))
|
|
2119
|
+
|
|
2120
|
+
blocks.append(
|
|
2121
|
+
Stripped(
|
|
2122
|
+
f"""\
|
|
2123
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2124
|
+
{transform_name}(
|
|
2125
|
+
{I}that: {cls_name},
|
|
2126
|
+
{I}other: Class
|
|
2127
|
+
): boolean {{
|
|
2128
|
+
{I}return {is_name}(other);
|
|
2129
|
+
}}
|
|
2130
|
+
/* eslint-enable @typescript-eslint/no-unused-vars */"""
|
|
2131
|
+
)
|
|
2132
|
+
)
|
|
2133
|
+
|
|
2134
|
+
writer = io.StringIO()
|
|
2135
|
+
writer.write(
|
|
2136
|
+
f"""\
|
|
2137
|
+
class TypeMatcher extends AbstractTransformerWithContext<
|
|
2138
|
+
{I}Readonly<Class>,
|
|
2139
|
+
{I}boolean
|
|
2140
|
+
> {{"""
|
|
2141
|
+
)
|
|
2142
|
+
|
|
2143
|
+
for i, block in enumerate(blocks):
|
|
2144
|
+
if i == 0:
|
|
2145
|
+
writer.write("\n")
|
|
2146
|
+
else:
|
|
2147
|
+
writer.write("\n\n")
|
|
2148
|
+
|
|
2149
|
+
writer.write(textwrap.indent(block, I))
|
|
2150
|
+
|
|
2151
|
+
writer.write("\n}")
|
|
2152
|
+
|
|
2153
|
+
return Stripped(writer.getvalue())
|
|
2154
|
+
|
|
2155
|
+
|
|
2156
|
+
# fmt: off
|
|
2157
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
2158
|
+
@ensure(
|
|
2159
|
+
lambda result:
|
|
2160
|
+
not (result[0] is not None) or result[0].endswith('\n'),
|
|
2161
|
+
"Trailing newline mandatory for valid end-of-files"
|
|
2162
|
+
)
|
|
2163
|
+
# fmt: on
|
|
2164
|
+
def generate(
|
|
2165
|
+
symbol_table: VerifiedIntermediateSymbolTable,
|
|
2166
|
+
spec_impls: specific_implementations.SpecificImplementations,
|
|
2167
|
+
) -> Tuple[Optional[str], Optional[List[Error]]]:
|
|
2168
|
+
"""
|
|
2169
|
+
Generate the TypeScript code of the structures based on the symbol table.
|
|
2170
|
+
|
|
2171
|
+
The ``aas_module`` indicates the fully-qualified name of the base module.
|
|
2172
|
+
"""
|
|
2173
|
+
errors = [] # type: List[Error]
|
|
2174
|
+
|
|
2175
|
+
blocks = [] # type: List[Stripped]
|
|
2176
|
+
|
|
2177
|
+
if symbol_table.meta_model.description is not None:
|
|
2178
|
+
# fmt: off
|
|
2179
|
+
comment, comment_errors = (
|
|
2180
|
+
_generate_comment_for_meta_model(
|
|
2181
|
+
description=symbol_table.meta_model.description
|
|
2182
|
+
)
|
|
2183
|
+
)
|
|
2184
|
+
# fmt: on
|
|
2185
|
+
|
|
2186
|
+
if comment_errors is not None:
|
|
2187
|
+
errors.extend(comment_errors)
|
|
2188
|
+
else:
|
|
2189
|
+
assert comment is not None
|
|
2190
|
+
blocks.append(comment)
|
|
2191
|
+
|
|
2192
|
+
model_type_getter = typescript_naming.method_name(Identifier("model_type"))
|
|
2193
|
+
|
|
2194
|
+
blocks.extend(
|
|
2195
|
+
[
|
|
2196
|
+
typescript_common.WARNING,
|
|
2197
|
+
_generate_model_type_enum(symbol_table=symbol_table),
|
|
2198
|
+
_generate_over_model_type_enum(symbol_table=symbol_table),
|
|
2199
|
+
Stripped(
|
|
2200
|
+
f"""\
|
|
2201
|
+
/**
|
|
2202
|
+
* Represent the most general class of an AAS model.
|
|
2203
|
+
*/
|
|
2204
|
+
export abstract class Class {{
|
|
2205
|
+
{I}/**
|
|
2206
|
+
{I} * Indicate the runtime model type of an instance.
|
|
2207
|
+
{I} */
|
|
2208
|
+
{I}abstract {model_type_getter}(): ModelType;
|
|
2209
|
+
|
|
2210
|
+
{I}/**
|
|
2211
|
+
{I} * Iterate over all the instances referenced from this one.
|
|
2212
|
+
{I} */
|
|
2213
|
+
{I}abstract descendOnce(): IterableIterator<Class>;
|
|
2214
|
+
|
|
2215
|
+
{I}/**
|
|
2216
|
+
{I} * Iterate recursively over all the instances referenced from this one.
|
|
2217
|
+
{I} */
|
|
2218
|
+
{I}abstract descend(): IterableIterator<Class>;
|
|
2219
|
+
|
|
2220
|
+
{I}/**
|
|
2221
|
+
{I} * Dispatch the `visitor` on this instance.
|
|
2222
|
+
{I} *
|
|
2223
|
+
{I} * @param visitor - to be dispatched
|
|
2224
|
+
{I} */
|
|
2225
|
+
{I}abstract accept(visitor: AbstractVisitor): void;
|
|
2226
|
+
|
|
2227
|
+
{I}/**
|
|
2228
|
+
{I} * Dispatch the `visitor` on this instance with `context`.
|
|
2229
|
+
{I} *
|
|
2230
|
+
{I} * @param visitor - to be dispatched
|
|
2231
|
+
{I} * @param context - of the visitation
|
|
2232
|
+
{I} * @typeParam ContextT - type of the visitation context
|
|
2233
|
+
{I} */
|
|
2234
|
+
{I}abstract acceptWithContext<ContextT>(
|
|
2235
|
+
{II}visitor: AbstractVisitorWithContext<ContextT>,
|
|
2236
|
+
{II}context: ContextT
|
|
2237
|
+
{I}): void;
|
|
2238
|
+
|
|
2239
|
+
{I}/**
|
|
2240
|
+
{I} * Dispatch the `transformer` on this instance.
|
|
2241
|
+
{I} *
|
|
2242
|
+
{I} * @param transformer - to be dispatched
|
|
2243
|
+
{I} * @return this instance transformed
|
|
2244
|
+
{I} * @typeParam T - type of the transformation result
|
|
2245
|
+
{I} */
|
|
2246
|
+
{I}abstract transform<T>(transformer: AbstractTransformer<T>): T;
|
|
2247
|
+
|
|
2248
|
+
{I}/**
|
|
2249
|
+
{I} * Dispatch the `transformer` on this instance in `context`.
|
|
2250
|
+
{I} *
|
|
2251
|
+
{I} * @param transformer - to be dispatched
|
|
2252
|
+
{I} * @param context - of the transformation
|
|
2253
|
+
{I} * @return this instance transformed
|
|
2254
|
+
{I} * @typeParam T - type of the transformation result
|
|
2255
|
+
{I} */
|
|
2256
|
+
{I}abstract transformWithContext<ContextT, T>(
|
|
2257
|
+
{II}transformer: AbstractTransformerWithContext<ContextT, T>,
|
|
2258
|
+
{II}context: ContextT
|
|
2259
|
+
{I}): T;
|
|
2260
|
+
}}"""
|
|
2261
|
+
),
|
|
2262
|
+
]
|
|
2263
|
+
)
|
|
2264
|
+
|
|
2265
|
+
concrete_class_to_index = {
|
|
2266
|
+
concrete_cls: i for i, concrete_cls in enumerate(symbol_table.concrete_classes)
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
for our_type in symbol_table.our_types:
|
|
2270
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
2271
|
+
block, error = _generate_enum(enum=our_type)
|
|
2272
|
+
if error is not None:
|
|
2273
|
+
errors.append(error)
|
|
2274
|
+
continue
|
|
2275
|
+
else:
|
|
2276
|
+
assert block is not None
|
|
2277
|
+
blocks.append(block)
|
|
2278
|
+
blocks.append(_generate_over_enum(enum=our_type))
|
|
2279
|
+
|
|
2280
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
2281
|
+
# NOTE (mristin, 2022-11-10):
|
|
2282
|
+
# We do not generate the constrained primitives as types. We only
|
|
2283
|
+
# consider them in the verification.
|
|
2284
|
+
continue
|
|
2285
|
+
|
|
2286
|
+
elif isinstance(
|
|
2287
|
+
our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
|
|
2288
|
+
):
|
|
2289
|
+
if our_type.is_implementation_specific:
|
|
2290
|
+
implementation_key = specific_implementations.ImplementationKey(
|
|
2291
|
+
f"Types/{our_type.name}.ts"
|
|
2292
|
+
)
|
|
2293
|
+
|
|
2294
|
+
block = spec_impls.get(implementation_key, None)
|
|
2295
|
+
if block is None:
|
|
2296
|
+
errors.append(
|
|
2297
|
+
Error(
|
|
2298
|
+
our_type.parsed.node,
|
|
2299
|
+
f"The implementation is missing "
|
|
2300
|
+
f"for the implementation-specific "
|
|
2301
|
+
f"class: {implementation_key}",
|
|
2302
|
+
)
|
|
2303
|
+
)
|
|
2304
|
+
else:
|
|
2305
|
+
blocks.append(block)
|
|
2306
|
+
else:
|
|
2307
|
+
if our_type.interface is not None:
|
|
2308
|
+
block, error = _generate_interface(interface=our_type.interface)
|
|
2309
|
+
if error is not None:
|
|
2310
|
+
errors.append(error)
|
|
2311
|
+
else:
|
|
2312
|
+
assert block is not None
|
|
2313
|
+
blocks.append(block)
|
|
2314
|
+
|
|
2315
|
+
if isinstance(our_type, intermediate.ConcreteClass):
|
|
2316
|
+
block, error = _generate_class(
|
|
2317
|
+
cls=our_type,
|
|
2318
|
+
spec_impls=spec_impls,
|
|
2319
|
+
concrete_cls_index=concrete_class_to_index[our_type],
|
|
2320
|
+
)
|
|
2321
|
+
if error is not None:
|
|
2322
|
+
errors.append(error)
|
|
2323
|
+
else:
|
|
2324
|
+
assert block is not None
|
|
2325
|
+
blocks.append(block)
|
|
2326
|
+
else:
|
|
2327
|
+
assert_never(our_type)
|
|
2328
|
+
|
|
2329
|
+
if len(errors) > 0:
|
|
2330
|
+
return None, errors
|
|
2331
|
+
|
|
2332
|
+
blocks.extend(
|
|
2333
|
+
[
|
|
2334
|
+
_generate_abstract_visitor(symbol_table=symbol_table),
|
|
2335
|
+
_generate_abstract_visitor_with_context(symbol_table=symbol_table),
|
|
2336
|
+
_generate_pass_through_visitor(symbol_table=symbol_table),
|
|
2337
|
+
_generate_pass_through_visitor_with_context(symbol_table=symbol_table),
|
|
2338
|
+
_generate_abstract_transformer(symbol_table=symbol_table),
|
|
2339
|
+
_generate_abstract_transformer_with_context(symbol_table=symbol_table),
|
|
2340
|
+
_generate_transformer_with_default(symbol_table=symbol_table),
|
|
2341
|
+
_generate_transformer_with_default_and_context(symbol_table=symbol_table),
|
|
2342
|
+
]
|
|
2343
|
+
)
|
|
2344
|
+
|
|
2345
|
+
for cls in symbol_table.classes:
|
|
2346
|
+
if cls.interface is not None:
|
|
2347
|
+
transformer_name = typescript_naming.class_name(
|
|
2348
|
+
Identifier(f"As_{cls.interface.name}_transformer")
|
|
2349
|
+
)
|
|
2350
|
+
constant_transformer = typescript_naming.constant_name(
|
|
2351
|
+
Identifier(f"As_{cls.interface.name}_transformer")
|
|
2352
|
+
)
|
|
2353
|
+
|
|
2354
|
+
as_interface = typescript_naming.function_name(
|
|
2355
|
+
Identifier(f"as_{cls.interface.name}")
|
|
2356
|
+
)
|
|
2357
|
+
|
|
2358
|
+
is_interface = typescript_naming.function_name(
|
|
2359
|
+
Identifier(f"is_{cls.interface.name}")
|
|
2360
|
+
)
|
|
2361
|
+
|
|
2362
|
+
interface_name = typescript_naming.interface_name(cls.interface.name)
|
|
2363
|
+
|
|
2364
|
+
blocks.extend(
|
|
2365
|
+
[
|
|
2366
|
+
_generate_as_interface_transformer(
|
|
2367
|
+
interface=cls.interface, symbol_table=symbol_table
|
|
2368
|
+
),
|
|
2369
|
+
Stripped(
|
|
2370
|
+
f"""\
|
|
2371
|
+
const {constant_transformer} =
|
|
2372
|
+
{I}new {transformer_name}();"""
|
|
2373
|
+
),
|
|
2374
|
+
Stripped(
|
|
2375
|
+
f"""\
|
|
2376
|
+
/**
|
|
2377
|
+
* Try to cast `that` instance to
|
|
2378
|
+
* the interface {{@link {interface_name}}}.
|
|
2379
|
+
*
|
|
2380
|
+
* @param that - instance to be casted
|
|
2381
|
+
* @returns - casted `that` if cast successful, or `null`
|
|
2382
|
+
*/
|
|
2383
|
+
export function {as_interface}(
|
|
2384
|
+
{I}that: Class
|
|
2385
|
+
): {interface_name} | null {{
|
|
2386
|
+
{I}return {constant_transformer}.transform(that);
|
|
2387
|
+
}}"""
|
|
2388
|
+
),
|
|
2389
|
+
Stripped(
|
|
2390
|
+
f"""\
|
|
2391
|
+
/**
|
|
2392
|
+
* Check the type of `that` instance.
|
|
2393
|
+
*
|
|
2394
|
+
* @param that - instance to be type-checked
|
|
2395
|
+
* @returns `true` if the type check is successful
|
|
2396
|
+
*/
|
|
2397
|
+
export function {is_interface}(
|
|
2398
|
+
{I}that: Class
|
|
2399
|
+
): that is {interface_name} {{
|
|
2400
|
+
{I}return {as_interface}(that) !== null;
|
|
2401
|
+
}}"""
|
|
2402
|
+
),
|
|
2403
|
+
]
|
|
2404
|
+
)
|
|
2405
|
+
|
|
2406
|
+
# NOTE (mristin, 2022-11-23):
|
|
2407
|
+
# We add these functions to make a uniform interface to ``isX`` checks.
|
|
2408
|
+
# Without these functions, the clients would have to refactor a lot once
|
|
2409
|
+
# the meta-model changes and a class gets descendants where it had none before.
|
|
2410
|
+
if (
|
|
2411
|
+
isinstance(cls, intermediate.ConcreteClass)
|
|
2412
|
+
and len(cls.concrete_descendants) == 0
|
|
2413
|
+
):
|
|
2414
|
+
cls_name = typescript_naming.class_name(cls.name)
|
|
2415
|
+
|
|
2416
|
+
as_cls = typescript_naming.function_name(Identifier(f"as_{cls.name}"))
|
|
2417
|
+
|
|
2418
|
+
is_cls = typescript_naming.function_name(Identifier(f"is_{cls.name}"))
|
|
2419
|
+
|
|
2420
|
+
blocks.extend(
|
|
2421
|
+
[
|
|
2422
|
+
Stripped(
|
|
2423
|
+
f"""\
|
|
2424
|
+
/**
|
|
2425
|
+
* Try to cast `that` instance to
|
|
2426
|
+
* the class {{@link {cls_name}}}.
|
|
2427
|
+
*
|
|
2428
|
+
* @param that - instance to be casted
|
|
2429
|
+
* @returns - casted `that` if cast successful, or `null`
|
|
2430
|
+
*/
|
|
2431
|
+
export function {as_cls}(
|
|
2432
|
+
{I}that: Class
|
|
2433
|
+
): {cls_name} | null {{
|
|
2434
|
+
{I}return (that instanceof {cls_name})
|
|
2435
|
+
{II}? <{cls_name}>that
|
|
2436
|
+
{II}: null;
|
|
2437
|
+
}}"""
|
|
2438
|
+
),
|
|
2439
|
+
Stripped(
|
|
2440
|
+
f"""\
|
|
2441
|
+
/**
|
|
2442
|
+
* Check the type of `that` instance.
|
|
2443
|
+
*
|
|
2444
|
+
* @param that - instance to be type-checked
|
|
2445
|
+
* @returns `true` if the type check is successful
|
|
2446
|
+
*/
|
|
2447
|
+
export function {is_cls}(
|
|
2448
|
+
{I}that: Class
|
|
2449
|
+
): that is {cls_name} {{
|
|
2450
|
+
{I}return that instanceof {cls_name};
|
|
2451
|
+
}}"""
|
|
2452
|
+
),
|
|
2453
|
+
]
|
|
2454
|
+
)
|
|
2455
|
+
|
|
2456
|
+
blocks.append(_generate_type_matcher(symbol_table=symbol_table))
|
|
2457
|
+
blocks.append(
|
|
2458
|
+
Stripped(
|
|
2459
|
+
"""\
|
|
2460
|
+
const TYPE_MATCHER = new TypeMatcher();"""
|
|
2461
|
+
)
|
|
2462
|
+
)
|
|
2463
|
+
|
|
2464
|
+
blocks.append(
|
|
2465
|
+
Stripped(
|
|
2466
|
+
f"""\
|
|
2467
|
+
/**
|
|
2468
|
+
* Check whether the type of `that` matches the type of `other` instance.
|
|
2469
|
+
*
|
|
2470
|
+
* @remarks
|
|
2471
|
+
* We check with `is*` function. Hence, if the class of `other` is a subclass of
|
|
2472
|
+
* the class of `that`, we confirm the match.
|
|
2473
|
+
*
|
|
2474
|
+
* @param that - standard instance
|
|
2475
|
+
* @param other - instance whose type is compared against `that`
|
|
2476
|
+
*/
|
|
2477
|
+
export function typesMatch<ClassT extends Class>(
|
|
2478
|
+
{I}that: ClassT,
|
|
2479
|
+
{I}other: Class
|
|
2480
|
+
): other is ClassT {{
|
|
2481
|
+
{I}return TYPE_MATCHER.transformWithContext(that, other);
|
|
2482
|
+
}}"""
|
|
2483
|
+
)
|
|
2484
|
+
)
|
|
2485
|
+
|
|
2486
|
+
blocks.append(typescript_common.WARNING)
|
|
2487
|
+
|
|
2488
|
+
out = io.StringIO()
|
|
2489
|
+
for i, block in enumerate(blocks):
|
|
2490
|
+
if i > 0:
|
|
2491
|
+
out.write("\n\n")
|
|
2492
|
+
|
|
2493
|
+
out.write(block)
|
|
2494
|
+
|
|
2495
|
+
out.write("\n")
|
|
2496
|
+
|
|
2497
|
+
return out.getvalue(), None
|
|
2498
|
+
|
|
2499
|
+
|
|
2500
|
+
# endregion
|