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.
Files changed (604) hide show
  1. aas_core_codegen/__init__.py +6 -0
  2. aas_core_codegen/__main__.py +8 -0
  3. aas_core_codegen/common.py +500 -0
  4. aas_core_codegen/cpp/__init__.py +1 -0
  5. aas_core_codegen/cpp/aas_common/__init__.py +6 -0
  6. aas_core_codegen/cpp/aas_common/_generate.py +713 -0
  7. aas_core_codegen/cpp/common.py +681 -0
  8. aas_core_codegen/cpp/constants/__init__.py +6 -0
  9. aas_core_codegen/cpp/constants/_generate.py +568 -0
  10. aas_core_codegen/cpp/description.py +654 -0
  11. aas_core_codegen/cpp/enhancing/__init__.py +4 -0
  12. aas_core_codegen/cpp/enhancing/_generate.py +993 -0
  13. aas_core_codegen/cpp/iteration/__init__.py +6 -0
  14. aas_core_codegen/cpp/iteration/_generate.py +2332 -0
  15. aas_core_codegen/cpp/jsonization/__init__.py +6 -0
  16. aas_core_codegen/cpp/jsonization/_generate.py +2619 -0
  17. aas_core_codegen/cpp/main.py +694 -0
  18. aas_core_codegen/cpp/naming.py +170 -0
  19. aas_core_codegen/cpp/optionaling.py +557 -0
  20. aas_core_codegen/cpp/pattern/__init__.py +6 -0
  21. aas_core_codegen/cpp/pattern/_generate.py +508 -0
  22. aas_core_codegen/cpp/revm/__init__.py +6 -0
  23. aas_core_codegen/cpp/revm/_generate.py +1149 -0
  24. aas_core_codegen/cpp/stringification/__init__.py +5 -0
  25. aas_core_codegen/cpp/stringification/_generate.py +955 -0
  26. aas_core_codegen/cpp/structure/__init__.py +7 -0
  27. aas_core_codegen/cpp/structure/_generate.py +1503 -0
  28. aas_core_codegen/cpp/transpilation.py +1383 -0
  29. aas_core_codegen/cpp/unrolling.py +159 -0
  30. aas_core_codegen/cpp/verification/__init__.py +6 -0
  31. aas_core_codegen/cpp/verification/_generate.py +3073 -0
  32. aas_core_codegen/cpp/visitation/__init__.py +6 -0
  33. aas_core_codegen/cpp/visitation/_generate.py +521 -0
  34. aas_core_codegen/cpp/wstringification/__init__.py +5 -0
  35. aas_core_codegen/cpp/wstringification/_generate.py +586 -0
  36. aas_core_codegen/cpp/xmlization/__init__.py +6 -0
  37. aas_core_codegen/cpp/xmlization/_generate.py +5373 -0
  38. aas_core_codegen/cpp/yielding.py +201 -0
  39. aas_core_codegen/csharp/__init__.py +1 -0
  40. aas_core_codegen/csharp/common.py +224 -0
  41. aas_core_codegen/csharp/constants/__init__.py +5 -0
  42. aas_core_codegen/csharp/constants/_generate.py +409 -0
  43. aas_core_codegen/csharp/copying/__init__.py +4 -0
  44. aas_core_codegen/csharp/copying/_generate.py +498 -0
  45. aas_core_codegen/csharp/description.py +1103 -0
  46. aas_core_codegen/csharp/enhancing/__init__.py +4 -0
  47. aas_core_codegen/csharp/enhancing/_generate.py +667 -0
  48. aas_core_codegen/csharp/jsonization/__init__.py +4 -0
  49. aas_core_codegen/csharp/jsonization/_generate.py +1630 -0
  50. aas_core_codegen/csharp/main.py +421 -0
  51. aas_core_codegen/csharp/naming.py +157 -0
  52. aas_core_codegen/csharp/reporting/__init__.py +4 -0
  53. aas_core_codegen/csharp/reporting/_generate.py +266 -0
  54. aas_core_codegen/csharp/stringification/__init__.py +4 -0
  55. aas_core_codegen/csharp/stringification/_generate.py +243 -0
  56. aas_core_codegen/csharp/structure/__init__.py +6 -0
  57. aas_core_codegen/csharp/structure/_generate.py +1341 -0
  58. aas_core_codegen/csharp/transpilation.py +990 -0
  59. aas_core_codegen/csharp/unrolling.py +211 -0
  60. aas_core_codegen/csharp/verification/__init__.py +6 -0
  61. aas_core_codegen/csharp/verification/_generate.py +1457 -0
  62. aas_core_codegen/csharp/visitation/__init__.py +5 -0
  63. aas_core_codegen/csharp/visitation/_generate.py +579 -0
  64. aas_core_codegen/csharp/xmlization/__init__.py +4 -0
  65. aas_core_codegen/csharp/xmlization/_generate.py +1980 -0
  66. aas_core_codegen/golang/__init__.py +1 -0
  67. aas_core_codegen/golang/aas_common/__init__.py +4 -0
  68. aas_core_codegen/golang/aas_common/_generate.py +152 -0
  69. aas_core_codegen/golang/common.py +303 -0
  70. aas_core_codegen/golang/constants/__init__.py +5 -0
  71. aas_core_codegen/golang/constants/_generate.py +339 -0
  72. aas_core_codegen/golang/description.py +501 -0
  73. aas_core_codegen/golang/enhancing/__init__.py +4 -0
  74. aas_core_codegen/golang/enhancing/_generate.py +527 -0
  75. aas_core_codegen/golang/jsonization/__init__.py +4 -0
  76. aas_core_codegen/golang/jsonization/_generate.py +1740 -0
  77. aas_core_codegen/golang/main.py +368 -0
  78. aas_core_codegen/golang/naming.py +412 -0
  79. aas_core_codegen/golang/pointering.py +631 -0
  80. aas_core_codegen/golang/reporting/__init__.py +4 -0
  81. aas_core_codegen/golang/reporting/_generate.py +218 -0
  82. aas_core_codegen/golang/stringification/__init__.py +4 -0
  83. aas_core_codegen/golang/stringification/_generate.py +394 -0
  84. aas_core_codegen/golang/structure/__init__.py +6 -0
  85. aas_core_codegen/golang/structure/_generate.py +1493 -0
  86. aas_core_codegen/golang/transpilation.py +1191 -0
  87. aas_core_codegen/golang/unrolling.py +159 -0
  88. aas_core_codegen/golang/verification/__init__.py +6 -0
  89. aas_core_codegen/golang/verification/_generate.py +1513 -0
  90. aas_core_codegen/golang/xmlization/__init__.py +4 -0
  91. aas_core_codegen/golang/xmlization/_generate.py +2507 -0
  92. aas_core_codegen/infer_for_schema/__init__.py +21 -0
  93. aas_core_codegen/infer_for_schema/_inline.py +693 -0
  94. aas_core_codegen/infer_for_schema/_len.py +527 -0
  95. aas_core_codegen/infer_for_schema/_pattern.py +311 -0
  96. aas_core_codegen/infer_for_schema/_set.py +394 -0
  97. aas_core_codegen/infer_for_schema/_stringify.py +201 -0
  98. aas_core_codegen/infer_for_schema/_types.py +135 -0
  99. aas_core_codegen/infer_for_schema/match.py +122 -0
  100. aas_core_codegen/intermediate/__init__.py +78 -0
  101. aas_core_codegen/intermediate/_hierarchy.py +397 -0
  102. aas_core_codegen/intermediate/_stringify.py +989 -0
  103. aas_core_codegen/intermediate/_translate.py +5128 -0
  104. aas_core_codegen/intermediate/_types.py +2901 -0
  105. aas_core_codegen/intermediate/construction.py +750 -0
  106. aas_core_codegen/intermediate/doc.py +344 -0
  107. aas_core_codegen/intermediate/pattern_verification.py +428 -0
  108. aas_core_codegen/intermediate/revm.py +985 -0
  109. aas_core_codegen/intermediate/type_inference.py +2266 -0
  110. aas_core_codegen/java/__init__.py +1 -0
  111. aas_core_codegen/java/common.py +197 -0
  112. aas_core_codegen/java/constants/__init__.py +5 -0
  113. aas_core_codegen/java/constants/_generate.py +334 -0
  114. aas_core_codegen/java/copying/__init__.py +4 -0
  115. aas_core_codegen/java/copying/_generate.py +502 -0
  116. aas_core_codegen/java/description.py +774 -0
  117. aas_core_codegen/java/enhancing/__init__.py +4 -0
  118. aas_core_codegen/java/enhancing/_generate.py +820 -0
  119. aas_core_codegen/java/generation/__init__.py +5 -0
  120. aas_core_codegen/java/generation/_generate.py +285 -0
  121. aas_core_codegen/java/jsonization/__init__.py +4 -0
  122. aas_core_codegen/java/jsonization/_generate.py +1472 -0
  123. aas_core_codegen/java/main.py +438 -0
  124. aas_core_codegen/java/naming.py +187 -0
  125. aas_core_codegen/java/optional.py +514 -0
  126. aas_core_codegen/java/reporting/__init__.py +4 -0
  127. aas_core_codegen/java/reporting/_generate.py +248 -0
  128. aas_core_codegen/java/stringification/__init__.py +4 -0
  129. aas_core_codegen/java/stringification/_generate.py +212 -0
  130. aas_core_codegen/java/structure/__init__.py +6 -0
  131. aas_core_codegen/java/structure/_generate.py +1767 -0
  132. aas_core_codegen/java/transpilation.py +1111 -0
  133. aas_core_codegen/java/verification/__init__.py +6 -0
  134. aas_core_codegen/java/verification/_generate.py +1536 -0
  135. aas_core_codegen/java/visitation/__init__.py +5 -0
  136. aas_core_codegen/java/visitation/_generate.py +689 -0
  137. aas_core_codegen/java/xmlization/__init__.py +4 -0
  138. aas_core_codegen/java/xmlization/_generate.py +2274 -0
  139. aas_core_codegen/jsonld/__init__.py +1 -0
  140. aas_core_codegen/jsonld/main.py +455 -0
  141. aas_core_codegen/jsonschema/__init__.py +1 -0
  142. aas_core_codegen/jsonschema/main.py +982 -0
  143. aas_core_codegen/main.py +245 -0
  144. aas_core_codegen/naming.py +133 -0
  145. aas_core_codegen/opcua/__init__.py +1 -0
  146. aas_core_codegen/opcua/main.py +1525 -0
  147. aas_core_codegen/opcua/naming.py +126 -0
  148. aas_core_codegen/parse/__init__.py +46 -0
  149. aas_core_codegen/parse/_rules.py +796 -0
  150. aas_core_codegen/parse/_stringify.py +532 -0
  151. aas_core_codegen/parse/_translate.py +3940 -0
  152. aas_core_codegen/parse/_types.py +973 -0
  153. aas_core_codegen/parse/retree/__init__.py +46 -0
  154. aas_core_codegen/parse/retree/_fix.py +434 -0
  155. aas_core_codegen/parse/retree/_parse.py +1143 -0
  156. aas_core_codegen/parse/retree/_render.py +298 -0
  157. aas_core_codegen/parse/retree/_stringify.py +199 -0
  158. aas_core_codegen/parse/retree/_types.py +362 -0
  159. aas_core_codegen/parse/retree/_visitor.py +70 -0
  160. aas_core_codegen/parse/tree.py +1303 -0
  161. aas_core_codegen/protobuf/__init__.py +1 -0
  162. aas_core_codegen/protobuf/common.py +225 -0
  163. aas_core_codegen/protobuf/description.py +1102 -0
  164. aas_core_codegen/protobuf/main.py +115 -0
  165. aas_core_codegen/protobuf/naming.py +143 -0
  166. aas_core_codegen/protobuf/structure/__init__.py +6 -0
  167. aas_core_codegen/protobuf/structure/_generate.py +502 -0
  168. aas_core_codegen/py.typed +1 -0
  169. aas_core_codegen/python/__init__.py +1 -0
  170. aas_core_codegen/python/aas_common/__init__.py +4 -0
  171. aas_core_codegen/python/aas_common/_generate.py +63 -0
  172. aas_core_codegen/python/common.py +406 -0
  173. aas_core_codegen/python/constants/__init__.py +5 -0
  174. aas_core_codegen/python/constants/_generate.py +377 -0
  175. aas_core_codegen/python/description.py +508 -0
  176. aas_core_codegen/python/jsonization/__init__.py +4 -0
  177. aas_core_codegen/python/jsonization/_generate.py +1391 -0
  178. aas_core_codegen/python/main.py +323 -0
  179. aas_core_codegen/python/naming.py +255 -0
  180. aas_core_codegen/python/stringification/__init__.py +4 -0
  181. aas_core_codegen/python/stringification/_generate.py +129 -0
  182. aas_core_codegen/python/structure/__init__.py +6 -0
  183. aas_core_codegen/python/structure/_generate.py +1801 -0
  184. aas_core_codegen/python/transpilation.py +958 -0
  185. aas_core_codegen/python/unrolling.py +156 -0
  186. aas_core_codegen/python/verification/__init__.py +6 -0
  187. aas_core_codegen/python/verification/_generate.py +1471 -0
  188. aas_core_codegen/python/xmlization/__init__.py +4 -0
  189. aas_core_codegen/python/xmlization/_generate.py +3003 -0
  190. aas_core_codegen/python_protobuf/__init__.py +1 -0
  191. aas_core_codegen/python_protobuf/main.py +1424 -0
  192. aas_core_codegen/python_protobuf/naming.py +85 -0
  193. aas_core_codegen/rdf_shacl/__init__.py +1 -0
  194. aas_core_codegen/rdf_shacl/_description.py +351 -0
  195. aas_core_codegen/rdf_shacl/common.py +206 -0
  196. aas_core_codegen/rdf_shacl/main.py +114 -0
  197. aas_core_codegen/rdf_shacl/naming.py +145 -0
  198. aas_core_codegen/rdf_shacl/rdf.py +435 -0
  199. aas_core_codegen/rdf_shacl/shacl.py +453 -0
  200. aas_core_codegen/run.py +124 -0
  201. aas_core_codegen/smoke/__init__.py +1 -0
  202. aas_core_codegen/smoke/main.py +219 -0
  203. aas_core_codegen/specific_implementations.py +72 -0
  204. aas_core_codegen/stringify.py +333 -0
  205. aas_core_codegen/typescript/__init__.py +1 -0
  206. aas_core_codegen/typescript/aas_common/__init__.py +4 -0
  207. aas_core_codegen/typescript/aas_common/_generate.py +472 -0
  208. aas_core_codegen/typescript/common.py +340 -0
  209. aas_core_codegen/typescript/constants/__init__.py +5 -0
  210. aas_core_codegen/typescript/constants/_generate.py +347 -0
  211. aas_core_codegen/typescript/description.py +530 -0
  212. aas_core_codegen/typescript/jsonization/__init__.py +4 -0
  213. aas_core_codegen/typescript/jsonization/_generate.py +1510 -0
  214. aas_core_codegen/typescript/main.py +258 -0
  215. aas_core_codegen/typescript/naming.py +189 -0
  216. aas_core_codegen/typescript/stringification/__init__.py +4 -0
  217. aas_core_codegen/typescript/stringification/_generate.py +367 -0
  218. aas_core_codegen/typescript/structure/__init__.py +6 -0
  219. aas_core_codegen/typescript/structure/_generate.py +2500 -0
  220. aas_core_codegen/typescript/transpilation.py +1051 -0
  221. aas_core_codegen/typescript/unrolling.py +159 -0
  222. aas_core_codegen/typescript/verification/__init__.py +6 -0
  223. aas_core_codegen/typescript/verification/_generate.py +1578 -0
  224. aas_core_codegen/xsd/__init__.py +1 -0
  225. aas_core_codegen/xsd/main.py +1187 -0
  226. aas_core_codegen/xsd/naming.py +83 -0
  227. aas_core_codegen/yielding/__init__.py +1 -0
  228. aas_core_codegen/yielding/flow.py +139 -0
  229. aas_core_codegen/yielding/linear.py +754 -0
  230. aas_core_codegen-0.0.16.dist-info/METADATA +211 -0
  231. aas_core_codegen-0.0.16.dist-info/RECORD +604 -0
  232. aas_core_codegen-0.0.16.dist-info/WHEEL +5 -0
  233. aas_core_codegen-0.0.16.dist-info/entry_points.txt +3 -0
  234. aas_core_codegen-0.0.16.dist-info/licenses/AUTHORS +9 -0
  235. aas_core_codegen-0.0.16.dist-info/licenses/LICENSE +23 -0
  236. aas_core_codegen-0.0.16.dist-info/top_level.txt +2 -0
  237. dev/continuous_integration/__init__.py +1 -0
  238. dev/continuous_integration/check_help_in_readme.py +208 -0
  239. dev/continuous_integration/check_init_and_pyproject_consistent.py +154 -0
  240. dev/continuous_integration/precommit.py +400 -0
  241. dev/dev_scripts/__init__.py +1 -0
  242. dev/dev_scripts/compare_rendered_regexes_against_source_py.py +42 -0
  243. dev/dev_scripts/copy_to_aas_core3_cpp.py +100 -0
  244. dev/dev_scripts/copy_to_aas_core3_java.py +90 -0
  245. dev/dev_scripts/download_latest_aas_core_meta_v3.py +114 -0
  246. dev/dev_scripts/draw_bipartite_graph_based_on_lines.py +37 -0
  247. dev/dev_scripts/run_tests_with_rerecord.py +69 -0
  248. dev/dev_scripts/update_to_aas_core_meta.py +174 -0
  249. dev/integration_tests/input/jsonschema/boilerplate/main.py +55 -0
  250. dev/integration_tests/input/meta_model.py +38 -0
  251. dev/integration_tests/input/python/boilerplate/main.py +153 -0
  252. dev/integration_tests/main.py +258 -0
  253. dev/test_data/csharp/test_structure/concrete_class_with_descendants/meta_model.py +15 -0
  254. dev/test_data/csharp/test_structure/constructor_without_arguments/all_properties_optional/meta_model.py +9 -0
  255. dev/test_data/csharp/test_structure/constructor_without_arguments/no_properties/meta_model.py +6 -0
  256. dev/test_data/csharp/test_verification/builtin_functions/len/on_list/meta_model.py +20 -0
  257. dev/test_data/csharp/test_verification/builtin_functions/len/on_str/meta_model.py +16 -0
  258. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_prefix/meta_model.py +8 -0
  259. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_suffix/meta_model.py +8 -0
  260. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_group_with_quantifier/meta_model.py +8 -0
  261. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_the_middle/meta_model.py +8 -0
  262. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_union/meta_model.py +8 -0
  263. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/single_utf32_literal/meta_model.py +8 -0
  264. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_within_group/meta_model.py +8 -0
  265. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_without_group/meta_model.py +8 -0
  266. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_beginning/meta_model.py +8 -0
  267. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_end/meta_model.py +8 -0
  268. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/in_the_middle/meta_model.py +8 -0
  269. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/multiple/meta_model.py +8 -0
  270. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single/meta_model.py +8 -0
  271. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single_with_quantifier/meta_model.py +8 -0
  272. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/mixed_with_non_utf32/meta_model.py +8 -0
  273. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/more_than_two_high_surrogates/meta_model.py +8 -0
  274. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges/meta_model.py +8 -0
  275. 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
  276. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate/meta_model.py +8 -0
  277. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate_with_quantifier/meta_model.py +8 -0
  278. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/two_high_surrogates/meta_model.py +8 -0
  279. dev/test_data/intermediate/expected/class/empty/meta_model.py +6 -0
  280. dev/test_data/intermediate/expected/class/implementation_specific_method/meta_model.py +8 -0
  281. dev/test_data/intermediate/expected/class/inheritance/meta_model.py +41 -0
  282. dev/test_data/intermediate/expected/class/methods_with_contracts/meta_model.py +15 -0
  283. dev/test_data/intermediate/expected/class/only_method_no_property/meta_model.py +7 -0
  284. dev/test_data/intermediate/expected/class/only_property_no_method/meta_model.py +9 -0
  285. dev/test_data/intermediate/expected/constant/constant_set/of_enum/meta_model.py +12 -0
  286. dev/test_data/intermediate/expected/constant/constant_set/of_str/meta_model.py +4 -0
  287. dev/test_data/intermediate/expected/constant/constant_set/with_description/meta_model.py +6 -0
  288. dev/test_data/intermediate/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
  289. dev/test_data/intermediate/expected/constant/constant_str/only_value/meta_model.py +7 -0
  290. dev/test_data/intermediate/expected/constant/constant_str/with_description/meta_model.py +5 -0
  291. dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_in_literal/meta_model.py +20 -0
  292. dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_outside_literal/meta_model.py +20 -0
  293. dev/test_data/intermediate/expected/empty/meta_model.py +2 -0
  294. dev/test_data/intermediate/expected/enumeration/meta_model.py +9 -0
  295. dev/test_data/intermediate/expected/interface/basic/meta_model.py +14 -0
  296. dev/test_data/intermediate/expected/interface/empty/meta_model.py +7 -0
  297. dev/test_data/intermediate/expected/interface/inheritance/meta_model.py +27 -0
  298. dev/test_data/intermediate/expected/interface/method_signature/meta_model.py +10 -0
  299. dev/test_data/intermediate/expected/interface/only_constructor/meta_model.py +11 -0
  300. dev/test_data/intermediate/expected/method/non_mutating/implementation_specific/meta_model.py +12 -0
  301. dev/test_data/intermediate/expected/method/non_mutating/understood/meta_model.py +11 -0
  302. dev/test_data/intermediate/expected/type_annotation/atomic/meta_model.py +9 -0
  303. dev/test_data/intermediate/expected/type_annotation/subscripted/class/meta_model.py +13 -0
  304. dev/test_data/intermediate/expected/type_annotation/subscripted/primitive/meta_model.py +9 -0
  305. dev/test_data/intermediate/unexpected/constant_set/of_enum/enumeration_literals_in_subset_outside_of_superset/meta_model.py +20 -0
  306. dev/test_data/intermediate/unexpected/constant_set/of_enum/invalid_literal/meta_model.py +11 -0
  307. dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_between_enumeration_and_literal/meta_model.py +30 -0
  308. dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_in_enumerations_between_subset_and_superset/meta_model.py +21 -0
  309. dev/test_data/intermediate/unexpected/constant_set/of_str/literals_in_subset_outside_of_superset/meta_model.py +18 -0
  310. dev/test_data/intermediate/unexpected/constant_set/of_str/mismatch_between_type_annotation_and_literals/meta_model.py +10 -0
  311. dev/test_data/intermediate/unexpected/constant_set/of_str/superset_and_subset_mismatch_in_type/meta_model.py +12 -0
  312. dev/test_data/intermediate/unexpected/constraints/dangling_constraintref/meta_model.py +18 -0
  313. dev/test_data/intermediate/unexpected/constraints/duplicate_constraints/meta_model.py +20 -0
  314. dev/test_data/intermediate/unexpected/documentation/unexpected_documentation_elements/meta_model.py +34 -0
  315. dev/test_data/intermediate/unexpected/invariant/class_invariant_uses_re/meta_model.py +10 -0
  316. dev/test_data/intermediate/unexpected/invariant/invariant_of_constrained_primitive_uses_re/meta_model.py +7 -0
  317. dev/test_data/intermediate/unexpected/invariant/unexpected_argument_count_to_len/meta_model.py +20 -0
  318. dev/test_data/intermediate/unexpected/invariant/unhandled_built_in_function/meta_model.py +16 -0
  319. dev/test_data/intermediate/unexpected/method_definitions/non_constant_default/meta_model.py +7 -0
  320. dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/default_non_none/meta_model.py +16 -0
  321. dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/no_default/meta_model.py +16 -0
  322. dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/after_inheritance/meta_model.py +58 -0
  323. dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/meta_model.py +9 -0
  324. dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/within_class/meta_model.py +22 -0
  325. dev/test_data/jsonschema/test_main/regression_when_len_constraints_on_inherited_property/meta_model.py +28 -0
  326. dev/test_data/opcua/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
  327. dev/test_data/opcua/test_main/classes_with_invariants/meta_model.py +21 -0
  328. dev/test_data/opcua/test_main/concrete_class_with_descendant/meta_model.py +27 -0
  329. dev/test_data/opcua/test_main/concrete_class_with_enum/meta_model.py +21 -0
  330. dev/test_data/opcua/test_main/concrete_class_with_list_of_instances/meta_model.py +21 -0
  331. dev/test_data/opcua/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
  332. dev/test_data/opcua/test_main/concrete_class_with_string/meta_model.py +13 -0
  333. dev/test_data/opcua/test_main/constrained_primitive/meta_model.py +20 -0
  334. dev/test_data/opcua/test_main/multiple_inheritance/meta_model.py +25 -0
  335. dev/test_data/parse/expected/constant/constant_set/of_enum/meta_model.py +12 -0
  336. dev/test_data/parse/expected/constant/constant_set/of_str/meta_model.py +4 -0
  337. dev/test_data/parse/expected/constant/constant_set/with_description/meta_model.py +6 -0
  338. dev/test_data/parse/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
  339. dev/test_data/parse/expected/constant/constant_str/only_value/meta_model.py +7 -0
  340. dev/test_data/parse/expected/constant/constant_str/with_description/meta_model.py +5 -0
  341. dev/test_data/parse/expected/enum/ok/meta_model.py +15 -0
  342. dev/test_data/parse/expected/implementation_specific_class/properties_and_methods_in_implementation_specific_class/meta_model.py +17 -0
  343. dev/test_data/parse/expected/inheritance/basic/meta_model.py +11 -0
  344. dev/test_data/parse/expected/inheritance/diamond/meta_model.py +26 -0
  345. dev/test_data/parse/expected/inheritance/inheritance_from_concrete_class/meta_model.py +10 -0
  346. dev/test_data/parse/expected/invariants/in_relation/meta_model.py +16 -0
  347. dev/test_data/parse/expected/method/arguments/meta_model.py +7 -0
  348. dev/test_data/parse/expected/method/basic/meta_model.py +7 -0
  349. dev/test_data/parse/expected/method/contracts/condition_as_keyword_argument/meta_model.py +8 -0
  350. dev/test_data/parse/expected/method/contracts/condition_as_positional_argument/meta_model.py +8 -0
  351. dev/test_data/parse/expected/method/contracts/description_as_keyword_argument/meta_model.py +8 -0
  352. dev/test_data/parse/expected/method/contracts/description_as_positional_argument/meta_model.py +8 -0
  353. dev/test_data/parse/expected/method/contracts/multiple_contracts_in_order/meta_model.py +17 -0
  354. dev/test_data/parse/expected/method/contracts/postcondition/basic/meta_model.py +10 -0
  355. dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_keyword_arguments/meta_model.py +9 -0
  356. dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_positional_arguments/meta_model.py +9 -0
  357. dev/test_data/parse/expected/method/default/meta_model.py +9 -0
  358. dev/test_data/parse/expected/method/description/meta_model.py +8 -0
  359. dev/test_data/parse/expected/method/is_implementation_specific/meta_model.py +8 -0
  360. dev/test_data/parse/expected/method/non_mutating/meta_model.py +11 -0
  361. dev/test_data/parse/expected/method/returns_none/meta_model.py +7 -0
  362. dev/test_data/parse/expected/method/returns_something/meta_model.py +7 -0
  363. dev/test_data/parse/expected/single_class/description/meta_model.py +12 -0
  364. dev/test_data/parse/expected/single_class/empty/meta_model.py +6 -0
  365. dev/test_data/parse/expected/single_class/property/description/meta_model.py +14 -0
  366. dev/test_data/parse/expected/single_class/property/mandatory/meta_model.py +6 -0
  367. dev/test_data/parse/expected/single_class/property/optional/meta_model.py +6 -0
  368. dev/test_data/parse/expected/single_class/property/recursion_to_entity/meta_model.py +6 -0
  369. dev/test_data/parse/unexpected/class_decorators/non_name_decorator/meta_model.py +7 -0
  370. dev/test_data/parse/unexpected/class_decorators/unknown_decorator/meta_model.py +7 -0
  371. dev/test_data/parse/unexpected/class_definitions/is_abstract_and_implementation_specific/meta_model.py +8 -0
  372. dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_before_a_method/meta_model.py +11 -0
  373. dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_for_a_pass/meta_model.py +9 -0
  374. dev/test_data/parse/unexpected/class_definitions/unexpected_double_description_for_a_property/meta_model.py +10 -0
  375. dev/test_data/parse/unexpected/class_inheritances/inheriting_from_implementation_specific_parent/meta_model.py +20 -0
  376. dev/test_data/parse/unexpected/class_inheritances/non_name_super_class/meta_model.py +6 -0
  377. dev/test_data/parse/unexpected/enum/expression_as_assignment_value/meta_model.py +6 -0
  378. dev/test_data/parse/unexpected/enum/non_assignment/meta_model.py +8 -0
  379. dev/test_data/parse/unexpected/enum/non_string_literal/meta_model.py +6 -0
  380. dev/test_data/parse/unexpected/enum/unexpected_inheritance/meta_model.py +6 -0
  381. dev/test_data/parse/unexpected/method_contracts/contract/non_lambda_condition/meta_model.py +8 -0
  382. dev/test_data/parse/unexpected/method_contracts/contract/non_string_literal_description/meta_model.py +8 -0
  383. dev/test_data/parse/unexpected/method_contracts/contract/without_any_arguments/meta_model.py +8 -0
  384. dev/test_data/parse/unexpected/method_contracts/contract/without_condition/meta_model.py +8 -0
  385. dev/test_data/parse/unexpected/method_contracts/postcondition/OLD_in_postcondition_without_snapshot/meta_model.py +8 -0
  386. dev/test_data/parse/unexpected/method_contracts/postcondition/argument_missing_in_function/meta_model.py +8 -0
  387. dev/test_data/parse/unexpected/method_contracts/precondition/argument_missing_in_function/meta_model.py +8 -0
  388. dev/test_data/parse/unexpected/method_contracts/snapshot/argument_missing_in_function/meta_model.py +8 -0
  389. dev/test_data/parse/unexpected/method_contracts/snapshot/capture_not_a_lambda/meta_model.py +8 -0
  390. dev/test_data/parse/unexpected/method_contracts/snapshot/invalid_name/meta_model.py +8 -0
  391. dev/test_data/parse/unexpected/method_contracts/snapshot/name_not_a_string_literal/meta_model.py +8 -0
  392. dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_capture/meta_model.py +8 -0
  393. dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_name/meta_model.py +8 -0
  394. dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_constructor/meta_model.py +8 -0
  395. dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_verification_function/meta_model.py +8 -0
  396. dev/test_data/parse/unexpected/method_decorators/non_name_decorator/meta_model.py +8 -0
  397. dev/test_data/parse/unexpected/method_decorators/unknown_call_decorator/meta_model.py +8 -0
  398. dev/test_data/parse/unexpected/method_decorators/unknown_name_decorator/meta_model.py +8 -0
  399. dev/test_data/parse/unexpected/method_definitions/argument_with_final/meta_model.py +7 -0
  400. dev/test_data/parse/unexpected/method_definitions/argument_without_a_type_annotation/meta_model.py +7 -0
  401. dev/test_data/parse/unexpected/method_definitions/default_for_self/meta_model.py +7 -0
  402. dev/test_data/parse/unexpected/method_definitions/dunder/meta_model.py +7 -0
  403. dev/test_data/parse/unexpected/method_definitions/init_with_return_type/meta_model.py +7 -0
  404. dev/test_data/parse/unexpected/method_definitions/with_keyword_only_arguments/meta_model.py +7 -0
  405. dev/test_data/parse/unexpected/method_definitions/with_positional_arguments/meta_model.py +7 -0
  406. dev/test_data/parse/unexpected/method_definitions/with_type_annotation_for_self/meta_model.py +7 -0
  407. dev/test_data/parse/unexpected/method_definitions/with_variable_arguments/meta_model.py +7 -0
  408. dev/test_data/parse/unexpected/method_definitions/with_variable_keyword_arguments/meta_model.py +7 -0
  409. dev/test_data/parse/unexpected/method_definitions/without_arguments/meta_model.py +7 -0
  410. dev/test_data/parse/unexpected/method_definitions/without_self/meta_model.py +7 -0
  411. dev/test_data/parse/unexpected/method_definitions/without_type_annotation_for_result/meta_model.py +7 -0
  412. dev/test_data/parse/unexpected/property_definitions/final_without_subscript/meta_model.py +6 -0
  413. dev/test_data/parse/unexpected/property_definitions/nested_final/meta_model.py +6 -0
  414. dev/test_data/parse/unexpected/property_definitions/non_simple/meta_model.py +6 -0
  415. dev/test_data/parse/unexpected/property_definitions/unexpected_assignment/meta_model.py +6 -0
  416. dev/test_data/parse/unexpected/property_definitions/unexpected_non_name_property/meta_model.py +6 -0
  417. dev/test_data/parse/unexpected/property_definitions/without_type_annotation/meta_model.py +6 -0
  418. dev/test_data/parse/unexpected/symbol_table/constant_set_with_a_non_set_subset/meta_model.py +6 -0
  419. dev/test_data/parse/unexpected/symbol_table/dangling_inheritance/meta_model.py +6 -0
  420. dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_a_property/meta_model.py +6 -0
  421. dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_an_argument/meta_model.py +7 -0
  422. dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_constant_set/meta_model.py +6 -0
  423. dev/test_data/parse/unexpected/symbol_table/dangling_subset_in_constant_set/meta_model.py +4 -0
  424. dev/test_data/parse/unexpected/symbol_table/inheritance_from_non_class/meta_model.py +10 -0
  425. dev/test_data/parse_retree/expected/character_set/common_escaping/source.py +1 -0
  426. dev/test_data/parse_retree/expected/character_set/complementing/double_caret/source.py +1 -0
  427. dev/test_data/parse_retree/expected/character_set/complementing/multiple_ranges/source.py +1 -0
  428. dev/test_data/parse_retree/expected/character_set/complementing/suffix_dash/source.py +1 -0
  429. dev/test_data/parse_retree/expected/character_set/escape_first_caret/source.py +1 -0
  430. dev/test_data/parse_retree/expected/character_set/literals_which_need_no_escaping_in_characters_set_but_need_escaping_outside/source.py +1 -0
  431. dev/test_data/parse_retree/expected/character_set/multiple_ranges/source.py +1 -0
  432. dev/test_data/parse_retree/expected/character_set/single_literal/source.py +1 -0
  433. dev/test_data/parse_retree/expected/character_set/single_range/source.py +1 -0
  434. dev/test_data/parse_retree/expected/character_set/unescaped_dash/only_dash/source.py +1 -0
  435. dev/test_data/parse_retree/expected/character_set/unescaped_dash/prefix_dash/source.py +1 -0
  436. dev/test_data/parse_retree/expected/character_set/unescaped_dash/suffix_dash/source.py +1 -0
  437. dev/test_data/parse_retree/expected/dot/source.py +1 -0
  438. dev/test_data/parse_retree/expected/empty/group/source.py +1 -0
  439. dev/test_data/parse_retree/expected/empty/group_in_a_group/source.py +1 -0
  440. dev/test_data/parse_retree/expected/empty/group_of_union_of_empty_concatenations/source.py +1 -0
  441. dev/test_data/parse_retree/expected/empty/regex/source.py +1 -0
  442. dev/test_data/parse_retree/expected/empty/union_of_empty_concatenations/source.py +1 -0
  443. dev/test_data/parse_retree/expected/escaped_literals/source.py +1 -0
  444. dev/test_data/parse_retree/expected/formatted_value/at_the_beginning/source.py +1 -0
  445. dev/test_data/parse_retree/expected/formatted_value/at_the_end/source.py +1 -0
  446. dev/test_data/parse_retree/expected/formatted_value/in_the_middle/source.py +1 -0
  447. dev/test_data/parse_retree/expected/formatted_value/single_formatted_value/source.py +1 -0
  448. dev/test_data/parse_retree/expected/literal/source.py +1 -0
  449. dev/test_data/parse_retree/expected/quantifier/greedy/at_least_3/source.py +1 -0
  450. dev/test_data/parse_retree/expected/quantifier/greedy/at_least_one/source.py +1 -0
  451. dev/test_data/parse_retree/expected/quantifier/greedy/at_most_3/source.py +1 -0
  452. dev/test_data/parse_retree/expected/quantifier/greedy/exactly_3/source.py +1 -0
  453. dev/test_data/parse_retree/expected/quantifier/greedy/maybe/source.py +1 -0
  454. dev/test_data/parse_retree/expected/quantifier/greedy/zero_or_more/source.py +1 -0
  455. dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_3/source.py +1 -0
  456. dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_one/source.py +1 -0
  457. dev/test_data/parse_retree/expected/quantifier/non_greedy/at_most_3/source.py +1 -0
  458. dev/test_data/parse_retree/expected/quantifier/non_greedy/exactly_3/source.py +1 -0
  459. dev/test_data/parse_retree/expected/quantifier/non_greedy/maybe/source.py +1 -0
  460. dev/test_data/parse_retree/expected/quantifier/non_greedy/zero_or_more/source.py +1 -0
  461. dev/test_data/parse_retree/expected/quantifier/on_a_character_set/source.py +1 -0
  462. dev/test_data/parse_retree/expected/quantifier/on_a_formatted_value/source.py +1 -0
  463. dev/test_data/parse_retree/expected/quantifier/on_a_group/source.py +1 -0
  464. dev/test_data/parse_retree/expected/quantifier/on_a_literal/source.py +1 -0
  465. dev/test_data/parse_retree/expected/start_and_stop_symbols/double_end_symbol/source.py +1 -0
  466. dev/test_data/parse_retree/expected/start_and_stop_symbols/double_start_symbol/source.py +1 -0
  467. dev/test_data/parse_retree/expected/start_and_stop_symbols/end_symbol_in_the_middle/source.py +1 -0
  468. dev/test_data/parse_retree/expected/start_and_stop_symbols/only_start_symbol/source.py +1 -0
  469. dev/test_data/parse_retree/expected/start_and_stop_symbols/only_stop_symbol/source.py +1 -0
  470. dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_at_the_beginning/source.py +1 -0
  471. dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_in_the_middle/source.py +1 -0
  472. dev/test_data/parse_retree/expected/start_and_stop_symbols/stop_symbol_at_the_end/source.py +1 -0
  473. dev/test_data/parse_retree/expected/union/of_character_sets/source.py +1 -0
  474. dev/test_data/parse_retree/expected/union/of_groups/source.py +1 -0
  475. dev/test_data/parse_retree/expected/union/of_string_literals/source.py +1 -0
  476. dev/test_data/parse_retree/expected/union/within_group/source.py +1 -0
  477. dev/test_data/parse_retree/expected/whitespace/source.py +1 -0
  478. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/Uxxxxxxxx_out_of_range/source.py +1 -0
  479. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/only_backslash/source.py +1 -0
  480. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_Uxxxxxxxx/source.py +1 -0
  481. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_uxxxx/source.py +1 -0
  482. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_x/source.py +1 -0
  483. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unexpected_escaping/source.py +1 -0
  484. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/digit/source.py +1 -0
  485. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_digit/source.py +1 -0
  486. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_whitespace/source.py +1 -0
  487. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_word/source.py +1 -0
  488. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/whitespace/source.py +1 -0
  489. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/word/source.py +1 -0
  490. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/Uxxxxxxxx_out_of_range/source.py +1 -0
  491. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/only_backslash/source.py +1 -0
  492. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_Uxxxxxxxx/source.py +1 -0
  493. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_uxxxx/source.py +1 -0
  494. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_x/source.py +1 -0
  495. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unexpected_escaping/source.py +1 -0
  496. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/digit/source.py +1 -0
  497. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_digit/source.py +1 -0
  498. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_whitespace/source.py +1 -0
  499. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_word/source.py +1 -0
  500. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/whitespace/source.py +1 -0
  501. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/word/source.py +1 -0
  502. dev/test_data/parse_retree/unexpected/invalid_character_range/source.py +1 -0
  503. dev/test_data/parse_retree/unexpected/invalid_quantifier/at_least_x/source.py +1 -0
  504. dev/test_data/parse_retree/unexpected/invalid_quantifier/between_3_and_x/source.py +1 -0
  505. dev/test_data/parse_retree/unexpected/invalid_quantifier/exactly_x/source.py +1 -0
  506. dev/test_data/parse_retree/unexpected/unhandled_group_directives/source.py +1 -0
  507. dev/test_data/parse_retree/unexpected/unterminated/character_set/source.py +1 -0
  508. dev/test_data/parse_retree/unexpected/unterminated/group/source.py +1 -0
  509. dev/test_data/parse_retree/unexpected/unterminated/group_of_union_of_empty_concatenations/source.py +1 -0
  510. dev/test_data/parse_retree/unexpected/unterminated/quantifier/source.py +1 -0
  511. dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_comma/source.py +1 -0
  512. dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_number_and_comma/source.py +1 -0
  513. dev/test_data/proto/test_main/expected/abstract_and_concrete_classes/meta_model.py +37 -0
  514. dev/test_data/proto/test_main/expected/concrete_class_with_descendants/meta_model.py +30 -0
  515. dev/test_data/proto/test_main/expected/concrete_class_with_enum/meta_model.py +21 -0
  516. dev/test_data/proto/test_main/expected/concrete_class_with_list_of_instances/meta_model.py +21 -0
  517. dev/test_data/proto/test_main/expected/concrete_class_with_primitive_attributes/meta_model.py +41 -0
  518. dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/expected_output/pbization.py +532 -0
  519. dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
  520. dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/expected_output/pbization.py +527 -0
  521. dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/meta_model.py +27 -0
  522. dev/test_data/python_protobuf/test_main/concrete_class_with_enum/expected_output/pbization.py +290 -0
  523. dev/test_data/python_protobuf/test_main/concrete_class_with_enum/meta_model.py +21 -0
  524. dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/expected_output/pbization.py +328 -0
  525. dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/meta_model.py +23 -0
  526. dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/expected_output/pbization.py +274 -0
  527. dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
  528. dev/test_data/rdf_shacl/test_main/expected/regression_when_lang_string_class_is_missing/meta_model.py +29 -0
  529. dev/test_data/rdf_shacl/test_main/expected/regression_when_len_constraints_on_inherited_property/meta_model.py +27 -0
  530. dev/test_data/rdf_shacl/test_main/unexpected/regression_len_constraint_on_class_property/meta_model.py +61 -0
  531. dev/test_data/real_meta_models/aas_core_meta.v3.py +5721 -0
  532. dev/test_data/smoke/test_main/unexpected/infer_for_schema_error/meta_model.py +12 -0
  533. dev/test_data/smoke/test_main/unexpected/intermediate_error/meta_model.py +18 -0
  534. dev/test_data/smoke/test_main/unexpected/parse_error/meta_model.py +5 -0
  535. dev/test_data/smoke/test_main/unexpected/pattern_verification_unparsable_regex/direct_match/meta_model.py +8 -0
  536. dev/test_data/smoke/test_main/unexpected/type_error/meta_model.py +18 -0
  537. dev/tests/__init__.py +1 -0
  538. dev/tests/common.py +197 -0
  539. dev/tests/cpp/__init__.py +0 -0
  540. dev/tests/cpp/test_common.py +32 -0
  541. dev/tests/cpp/test_main.py +144 -0
  542. dev/tests/cpp/test_pattern.py +188 -0
  543. dev/tests/cpp/test_verification.py +189 -0
  544. dev/tests/cpp/test_yielding.py +225 -0
  545. dev/tests/csharp/__init__.py +0 -0
  546. dev/tests/csharp/live_test_main.py +109 -0
  547. dev/tests/csharp/test_common.py +28 -0
  548. dev/tests/csharp/test_description.py +684 -0
  549. dev/tests/csharp/test_main.py +129 -0
  550. dev/tests/csharp/test_structure.py +93 -0
  551. dev/tests/csharp/test_verification.py +82 -0
  552. dev/tests/description.py +29 -0
  553. dev/tests/golang/__init__.py +0 -0
  554. dev/tests/golang/test_common.py +78 -0
  555. dev/tests/golang/test_main.py +128 -0
  556. dev/tests/infer_for_schema/__init__.py +0 -0
  557. dev/tests/infer_for_schema/common.py +47 -0
  558. dev/tests/infer_for_schema/test_len_on_properties.py +955 -0
  559. dev/tests/infer_for_schema/test_len_on_self.py +580 -0
  560. dev/tests/infer_for_schema/test_patterns_on_properties.py +686 -0
  561. dev/tests/infer_for_schema/test_patterns_on_self.py +258 -0
  562. dev/tests/infer_for_schema/test_property_in_set_of_enumeration_literals.py +600 -0
  563. dev/tests/infer_for_schema/test_property_in_set_of_primitives.py +549 -0
  564. dev/tests/intermediate/__init__.py +0 -0
  565. dev/tests/intermediate/test_constructor.py +719 -0
  566. dev/tests/intermediate/test_hierarchy.py +221 -0
  567. dev/tests/intermediate/test_revm.py +134 -0
  568. dev/tests/intermediate/test_translate.py +337 -0
  569. dev/tests/intermediate/test_type_inference.py +333 -0
  570. dev/tests/intermediate/test_types.py +169 -0
  571. dev/tests/java/__init__.py +0 -0
  572. dev/tests/java/test_common.py +20 -0
  573. dev/tests/java/test_description.py +128 -0
  574. dev/tests/java/test_main.py +234 -0
  575. dev/tests/jsonld_context/test_main.py +79 -0
  576. dev/tests/opcua/__init__.py +3 -0
  577. dev/tests/opcua/test_main.py +110 -0
  578. dev/tests/our_jsonschema/__init__.py +3 -0
  579. dev/tests/our_jsonschema/test_main.py +232 -0
  580. dev/tests/parse/__init__.py +0 -0
  581. dev/tests/parse/test_parse.py +503 -0
  582. dev/tests/parse/test_retree.py +272 -0
  583. dev/tests/proto/__init__.py +0 -0
  584. dev/tests/proto/test_main.py +112 -0
  585. dev/tests/python/__init__.py +0 -0
  586. dev/tests/python/test_common.py +124 -0
  587. dev/tests/python/test_main.py +126 -0
  588. dev/tests/python/test_xml_playground.py +254 -0
  589. dev/tests/python_protobuf/__init__.py +0 -0
  590. dev/tests/python_protobuf/test_main.py +111 -0
  591. dev/tests/rdf_shacl/__init__.py +0 -0
  592. dev/tests/rdf_shacl/test_common.py +32 -0
  593. dev/tests/rdf_shacl/test_description.py +223 -0
  594. dev/tests/rdf_shacl/test_main.py +194 -0
  595. dev/tests/smoke/__init__.py +0 -0
  596. dev/tests/smoke/test_main.py +83 -0
  597. dev/tests/test_common.py +94 -0
  598. dev/tests/typescript/__init__.py +0 -0
  599. dev/tests/typescript/test_common.py +108 -0
  600. dev/tests/typescript/test_main.py +125 -0
  601. dev/tests/xsd/__init__.py +0 -0
  602. dev/tests/xsd/test_main.py +227 -0
  603. dev/tests/yielding/__init__.py +0 -0
  604. 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