expressir 1.2.10-aarch64-linux → 2.4.29-aarch64-linux

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 (467) hide show
  1. checksums.yaml +4 -4
  2. data/.cargo/config.toml +3 -0
  3. data/.github/scripts/test_installed_gem.rb +34 -0
  4. data/.github/workflows/codeql.yml +35 -0
  5. data/.github/workflows/docs.yml +99 -0
  6. data/.github/workflows/links.yml +100 -0
  7. data/.github/workflows/native-gems.yml +201 -0
  8. data/.github/workflows/rake.yml +10 -296
  9. data/.github/workflows/release.yml +26 -114
  10. data/.github/workflows/rust-ext.yml +41 -0
  11. data/.github/workflows/stress.yml +36 -0
  12. data/.github/workflows/validate_schemas.yml +48 -0
  13. data/.github/workflows/verify_remarks.yml +33 -0
  14. data/.gitignore +33 -1
  15. data/.rubocop.yml +11 -11
  16. data/.rubocop_todo.yml +297 -0
  17. data/CHANGELOG.md +159 -0
  18. data/Gemfile +15 -1
  19. data/README.adoc +2675 -47
  20. data/Rakefile +34 -10
  21. data/TODO.bugs/01-stale-transformer-autoload.md +39 -0
  22. data/TODO.bugs/02-parser-class-instance-vars.md +36 -0
  23. data/TODO.bugs/03-builder-mutable-state.md +43 -0
  24. data/TODO.bugs/04-formatter-public-send-dispatch.md +53 -0
  25. data/TODO.bugs/05-anonymous-formatter-subclass.md +45 -0
  26. data/TODO.bugs/06-collection-registry-single-source.md +53 -0
  27. data/TODO.bugs/07-require-relative-cleanup.md +42 -0
  28. data/TODO.bugs/08-require-expressir-in-commands.md +34 -0
  29. data/TODO.bugs/09-parser-split.md +53 -0
  30. data/TODO.bugs/10-to-s-override.md +42 -0
  31. data/TODO.bugs/11-parser-class-variables.md +39 -0
  32. data/TODO.bugs/12-marker-modules-vs-registry.md +64 -0
  33. data/TODO.bugs/13-string-literal-scanner-limitation.md +52 -0
  34. data/TODO.bugs/14-model-formatting-leak.md +30 -0
  35. data/TODO.bugs/15-expression-children-macro.md +27 -0
  36. data/TODO.bugs/16-pretty-formatter-duplication.md +28 -0
  37. data/TODO.bugs/17-snake-case-cache-mutable-constant.md +28 -0
  38. data/TODO.bugs/18-const-get-private-constants.md +30 -0
  39. data/TODO.bugs/19-format-methods-public.md +22 -0
  40. data/TODO.bugs/20-coverage-nested-entities-dedup.md +20 -0
  41. data/TODO.bugs/21-operator-tokens-secondary-dispatch.md +21 -0
  42. data/TODO.bugs/22-builder-fast-path-wrappers.md +32 -0
  43. data/TODO.bugs/23-coverage-inverse-maps.md +21 -0
  44. data/TODO.bugs/24-streaming-builder-complexity.md +19 -0
  45. data/TODO.bugs/25-debug-puts-in-production.md +21 -0
  46. data/TODO.bugs/26-generic-entity-children-misplaced.md +21 -0
  47. data/TODO.bugs/27-package-build-god-method.md +19 -0
  48. data/TODO.bugs/28-package-god-class.md +30 -0
  49. data/TODO.bugs/29-validate-ascii-god-class.md +24 -0
  50. data/TODO.bugs/30-unicode-map-extraction.md +19 -0
  51. data/TODO.bugs/README.md +43 -0
  52. data/TODO.max-perf/01-restore-ci-green.md +36 -0
  53. data/TODO.max-perf/02-streaming-parse-path.md +31 -0
  54. data/TODO.max-perf/03-cli-parallel-opt-in.md +27 -0
  55. data/TODO.max-perf/04-benchmark-harness.md +28 -0
  56. data/TODO.max-perf/05-parallel-fidelity-specs.md +22 -0
  57. data/TODO.max-perf/06-builder-cpu-audit.md +41 -0
  58. data/TODO.max-perf/07-upstream-parsanol-roadmap.md +27 -0
  59. data/TODO.max-perf/08-builder-build-perf.md +45 -0
  60. data/TODO.max-perf/09-grammar-cold-start.md +25 -0
  61. data/TODO.max-perf/10-parser-facade-hygiene.md +23 -0
  62. data/TODO.max-perf/11-ci-green-closeout.md +25 -0
  63. data/TODO.max-perf/12-require-boot-profile.md +25 -0
  64. data/TODO.max-perf/13-key-conversion-specs.md +26 -0
  65. data/TODO.max-perf/14-builder-call-handler-audit.md +28 -0
  66. data/TODO.parity-ee/00-overview.md +76 -0
  67. data/TODO.parity-ee/01-annex-g-rule-extraction.md +41 -0
  68. data/TODO.parity-ee/02-eeng-algorithm-inventory.md +8 -0
  69. data/TODO.parity-ee/03-eeng-oracle-harness.md +33 -0
  70. data/TODO.parity-ee/04-shtolo-concatenate.md +44 -0
  71. data/TODO.parity-ee/05-shtolo-longform-flatten.md +53 -0
  72. data/TODO.parity-ee/06-interface-scheduling-parity.md +47 -0
  73. data/TODO.parity-ee/07-semantic-checks-port.md +35 -0
  74. data/TODO.parity-ee/08-pretty-roundtrip-gate.md +27 -0
  75. data/TODO.parity-ee/09-smrl-index-and-listing.md +22 -0
  76. data/TODO.parity-ee/10-interface-dot-graph.md +21 -0
  77. data/TODO.parity-ee/11-import-eeng-tests.md +79 -0
  78. data/TODO.parity-ee/12-full-check-catalog.md +67 -0
  79. data/TODO.parity-ee/13-population-p21.md +54 -0
  80. data/TODO.parity-ee/14-shtolo-completion.md +44 -0
  81. data/TODO.parity-ee/15-part28-xml.md +51 -0
  82. data/TODO.parity-ee/16-compare-patch.md +48 -0
  83. data/TODO.parity-ee/17-official-tests.md +42 -0
  84. data/TODO.parity-ee/18-mim-mapping.md +47 -0
  85. data/TODO.parity-ee/19-architecture.md +97 -0
  86. data/TODO.parity-ee/parity-matrix.md +108 -0
  87. data/TODO.refpath-v2/00-overview.md +64 -0
  88. data/TODO.suma-improvements/00-overview.md +23 -0
  89. data/TODO.suma-improvements/01-prebuilt-platform-gems.md +33 -0
  90. data/TODO.suma-improvements/02-suma-e2e.md +39 -0
  91. data/TODO.suma-improvements/03-item-graph.md +22 -0
  92. data/TODO.suma-improvements/04-compiled-set-default.md +16 -0
  93. data/TODO.suma-improvements/05-validation-in-docs.md +17 -0
  94. data/TODO.suma-improvements/06-memory-remeasure.md +36 -0
  95. data/TODO.suma-improvements/07-part28-xml.md +15 -0
  96. data/TODO.suma-improvements/08-windows-gnu-toolchain.md +15 -0
  97. data/TODO.suma-improvements/09-checker-tranche3.md +13 -0
  98. data/TODO.suma-improvements/10-expressdoc.md +8 -0
  99. data/benchmark/srl_benchmark.rb +458 -0
  100. data/benchmark/srl_native_benchmark.rb +146 -0
  101. data/benchmark/srl_ruby_benchmark.rb +132 -0
  102. data/bin/rspec +2 -1
  103. data/docs/Gemfile +12 -0
  104. data/docs/_config.yml +141 -0
  105. data/docs/_guides/changes/changes-format.adoc +778 -0
  106. data/docs/_guides/changes/importing-eengine.adoc +898 -0
  107. data/docs/_guides/changes/index.adoc +396 -0
  108. data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
  109. data/docs/_guides/changes/validating-changes.adoc +681 -0
  110. data/docs/_guides/cli/benchmark-performance.adoc +834 -0
  111. data/docs/_guides/cli/coverage-analysis.adoc +921 -0
  112. data/docs/_guides/cli/format-schemas.adoc +547 -0
  113. data/docs/_guides/cli/index.adoc +8 -0
  114. data/docs/_guides/cli/managing-changes.adoc +927 -0
  115. data/docs/_guides/cli/validate-ascii.adoc +645 -0
  116. data/docs/_guides/cli/validate-schemas.adoc +534 -0
  117. data/docs/_guides/formatter/formatter-architecture.adoc +401 -0
  118. data/docs/_guides/index.adoc +165 -0
  119. data/docs/_guides/ler/creating-packages.adoc +664 -0
  120. data/docs/_guides/ler/index.adoc +305 -0
  121. data/docs/_guides/ler/loading-packages.adoc +707 -0
  122. data/docs/_guides/ler/package-formats.adoc +748 -0
  123. data/docs/_guides/ler/querying-packages.adoc +826 -0
  124. data/docs/_guides/ler/step-packages.adoc +385 -0
  125. data/docs/_guides/ler/validating-packages.adoc +750 -0
  126. data/docs/_guides/liquid/basic-templates.adoc +813 -0
  127. data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
  128. data/docs/_guides/liquid/drops-reference.adoc +829 -0
  129. data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
  130. data/docs/_guides/liquid/index.adoc +468 -0
  131. data/docs/_guides/manifests/creating-manifests.adoc +483 -0
  132. data/docs/_guides/manifests/index.adoc +307 -0
  133. data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
  134. data/docs/_guides/manifests/validating-manifests.adoc +713 -0
  135. data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
  136. data/docs/_guides/ruby-api/index.adoc +257 -0
  137. data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
  138. data/docs/_guides/ruby-api/search-engine.adoc +609 -0
  139. data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
  140. data/docs/_pages/data-model.adoc +665 -0
  141. data/docs/_pages/express-language.adoc +506 -0
  142. data/docs/_pages/getting-started.adoc +414 -0
  143. data/docs/_pages/index.adoc +116 -0
  144. data/docs/_pages/introduction.adoc +256 -0
  145. data/docs/_pages/ler-packages.adoc +837 -0
  146. data/docs/_pages/parsers.adoc +709 -0
  147. data/docs/_pages/schema-manifests.adoc +431 -0
  148. data/docs/_references/index.adoc +228 -0
  149. data/docs/_tutorials/creating-ler-package.adoc +735 -0
  150. data/docs/_tutorials/documentation-coverage.adoc +795 -0
  151. data/docs/_tutorials/formatting-schemas.adoc +89 -0
  152. data/docs/_tutorials/index.adoc +231 -0
  153. data/docs/_tutorials/liquid-templates.adoc +806 -0
  154. data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
  155. data/docs/_tutorials/querying-schemas.adoc +751 -0
  156. data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
  157. data/docs/index.adoc +242 -0
  158. data/docs/lychee.toml +90 -0
  159. data/examples/demo_ler_usage.sh +86 -0
  160. data/examples/ler/README.md +111 -0
  161. data/examples/ler/simple_example.ler +0 -0
  162. data/examples/ler/simple_schema.exp +33 -0
  163. data/examples/ler_build.rb +75 -0
  164. data/examples/ler_cli.rb +79 -0
  165. data/examples/ler_demo_complete.rb +276 -0
  166. data/examples/ler_query.rb +91 -0
  167. data/examples/ler_query_examples.rb +305 -0
  168. data/examples/ler_stats.rb +81 -0
  169. data/examples/phase3_demo.rb +159 -0
  170. data/examples/query_demo_simple.rb +131 -0
  171. data/exe/expressir +6 -17
  172. data/exe/expressir-format +14 -0
  173. data/exe/{format-test → expressir-format-test} +8 -7
  174. data/expressir.gemspec +50 -37
  175. data/lib/expressir/3.2/expressir_core.so +0 -0
  176. data/lib/expressir/3.3/expressir_core.so +0 -0
  177. data/lib/expressir/3.4/expressir_core.so +0 -0
  178. data/lib/expressir/4.0/expressir_core.so +0 -0
  179. data/lib/expressir/benchmark.rb +310 -0
  180. data/lib/expressir/changes/item_change.rb +20 -0
  181. data/lib/expressir/changes/mapping_change.rb +16 -0
  182. data/lib/expressir/changes/schema_change.rb +85 -0
  183. data/lib/expressir/changes/version_change.rb +26 -0
  184. data/lib/expressir/changes.rb +9 -0
  185. data/lib/expressir/cli.rb +138 -11
  186. data/lib/expressir/commands/base.rb +25 -0
  187. data/lib/expressir/commands/benchmark.rb +59 -0
  188. data/lib/expressir/commands/benchmark_cache.rb +80 -0
  189. data/lib/expressir/commands/changes.rb +34 -0
  190. data/lib/expressir/commands/changes_import_eengine.rb +146 -0
  191. data/lib/expressir/commands/changes_validate.rb +63 -0
  192. data/lib/expressir/commands/check.rb +56 -0
  193. data/lib/expressir/commands/clean.rb +20 -0
  194. data/lib/expressir/commands/coverage.rb +458 -0
  195. data/lib/expressir/commands/expand.rb +26 -0
  196. data/lib/expressir/commands/file_violations.rb +70 -0
  197. data/lib/expressir/commands/fix.rb +33 -0
  198. data/lib/expressir/commands/flatten.rb +29 -0
  199. data/lib/expressir/commands/format.rb +43 -0
  200. data/lib/expressir/commands/manifest.rb +420 -0
  201. data/lib/expressir/commands/mapping_validate.rb +68 -0
  202. data/lib/expressir/commands/non_ascii_character.rb +49 -0
  203. data/lib/expressir/commands/non_ascii_violation_collection.rb +301 -0
  204. data/lib/expressir/commands/package.rb +1222 -0
  205. data/lib/expressir/commands/parity_inputs.rb +160 -0
  206. data/lib/expressir/commands/validate.rb +106 -0
  207. data/lib/expressir/commands/validate_ascii.rb +94 -0
  208. data/lib/expressir/commands/validate_load.rb +91 -0
  209. data/lib/expressir/commands/version.rb +9 -0
  210. data/lib/expressir/commands/xsd.rb +23 -0
  211. data/lib/expressir/commands.rb +30 -0
  212. data/lib/expressir/config.rb +40 -3
  213. data/lib/expressir/coverage.rb +510 -0
  214. data/lib/expressir/eengine/arm_compare_report.rb +23 -0
  215. data/lib/expressir/eengine/changes_section.rb +16 -0
  216. data/lib/expressir/eengine/compare_report.rb +69 -0
  217. data/lib/expressir/eengine/mim_compare_report.rb +23 -0
  218. data/lib/expressir/eengine/modified_object.rb +21 -0
  219. data/lib/expressir/eengine.rb +9 -0
  220. data/lib/expressir/errors.rb +113 -0
  221. data/lib/expressir/express/adoc_hyperlink_formatter.rb +30 -0
  222. data/lib/expressir/express/adoc_source_formatter.rb +12 -0
  223. data/lib/expressir/express/ast_key_converter.rb +114 -0
  224. data/lib/expressir/express/builder.rb +277 -0
  225. data/lib/expressir/express/builder_context.rb +22 -0
  226. data/lib/expressir/express/builder_registry.rb +397 -0
  227. data/lib/expressir/express/builders/attribute_decl_builder.rb +32 -0
  228. data/lib/expressir/express/builders/built_in_builder.rb +75 -0
  229. data/lib/expressir/express/builders/constant_builder.rb +108 -0
  230. data/lib/expressir/express/builders/declaration_builder.rb +20 -0
  231. data/lib/expressir/express/builders/derive_clause_builder.rb +14 -0
  232. data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
  233. data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
  234. data/lib/expressir/express/builders/entity_decl_builder.rb +116 -0
  235. data/lib/expressir/express/builders/explicit_attr_builder.rb +49 -0
  236. data/lib/expressir/express/builders/expression_builder.rb +416 -0
  237. data/lib/expressir/express/builders/function_decl_builder.rb +86 -0
  238. data/lib/expressir/express/builders/helpers.rb +148 -0
  239. data/lib/expressir/express/builders/interface_builder.rb +151 -0
  240. data/lib/expressir/express/builders/inverse_attr_builder.rb +43 -0
  241. data/lib/expressir/express/builders/inverse_attr_type_builder.rb +30 -0
  242. data/lib/expressir/express/builders/inverse_clause_builder.rb +14 -0
  243. data/lib/expressir/express/builders/literal_builder.rb +93 -0
  244. data/lib/expressir/express/builders/procedure_decl_builder.rb +82 -0
  245. data/lib/expressir/express/builders/qualifier_builder.rb +102 -0
  246. data/lib/expressir/express/builders/reference_builder.rb +18 -0
  247. data/lib/expressir/express/builders/rule_decl_builder.rb +97 -0
  248. data/lib/expressir/express/builders/schema_body_decl_builder.rb +18 -0
  249. data/lib/expressir/express/builders/schema_decl_builder.rb +56 -0
  250. data/lib/expressir/express/builders/schema_version_builder.rb +34 -0
  251. data/lib/expressir/express/builders/simple_id_builder.rb +17 -0
  252. data/lib/expressir/express/builders/statement_builder.rb +243 -0
  253. data/lib/expressir/express/builders/subtype_constraint_builder.rb +166 -0
  254. data/lib/expressir/express/builders/syntax_builder.rb +30 -0
  255. data/lib/expressir/express/builders/type_builder.rb +238 -0
  256. data/lib/expressir/express/builders/type_decl_builder.rb +26 -0
  257. data/lib/expressir/express/builders/unique_clause_builder.rb +20 -0
  258. data/lib/expressir/express/builders/unique_rule_builder.rb +41 -0
  259. data/lib/expressir/express/builders/where_clause_builder.rb +20 -0
  260. data/lib/expressir/express/builders.rb +55 -0
  261. data/lib/expressir/express/cache.rb +43 -18
  262. data/lib/expressir/express/checker.rb +812 -0
  263. data/lib/expressir/express/concatenator.rb +79 -0
  264. data/lib/expressir/express/core.rb +95 -0
  265. data/lib/expressir/express/error.rb +124 -0
  266. data/lib/expressir/express/formatter.rb +89 -1548
  267. data/lib/expressir/express/formatters/data_types_formatter.rb +362 -0
  268. data/lib/expressir/express/formatters/declarations_formatter.rb +753 -0
  269. data/lib/expressir/express/formatters/expressions_formatter.rb +180 -0
  270. data/lib/expressir/express/formatters/literals_formatter.rb +55 -0
  271. data/lib/expressir/express/formatters/references_formatter.rb +53 -0
  272. data/lib/expressir/express/formatters/remark_formatter.rb +270 -0
  273. data/lib/expressir/express/formatters/remark_item_formatter.rb +28 -0
  274. data/lib/expressir/express/formatters/statements_formatter.rb +272 -0
  275. data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +54 -0
  276. data/lib/expressir/express/formatters.rb +22 -0
  277. data/lib/expressir/express/grammar/parser.rb +712 -0
  278. data/lib/expressir/express/grammar.rb +11 -0
  279. data/lib/expressir/express/hyperlink_formatter.rb +4 -5
  280. data/lib/expressir/express/interface_dot.rb +105 -0
  281. data/lib/expressir/express/lazy_repository.rb +211 -0
  282. data/lib/expressir/express/line_map.rb +48 -0
  283. data/lib/expressir/express/listing.rb +174 -0
  284. data/lib/expressir/express/model_traversal.rb +42 -0
  285. data/lib/expressir/express/model_visitor.rb +11 -10
  286. data/lib/expressir/express/node_position_index.rb +342 -0
  287. data/lib/expressir/express/parallel_files.rb +229 -0
  288. data/lib/expressir/express/parser.rb +501 -62
  289. data/lib/expressir/express/pretty_formatter.rb +586 -0
  290. data/lib/expressir/express/pretty_gate.rb +61 -0
  291. data/lib/expressir/express/refs_overlay.rb +47 -0
  292. data/lib/expressir/express/remark_attacher.rb +1098 -0
  293. data/lib/expressir/express/remark_overlay.rb +86 -0
  294. data/lib/expressir/express/remark_scanner.rb +245 -0
  295. data/lib/expressir/express/resolve_references_model_visitor.rb +7 -9
  296. data/lib/expressir/express/schema_block_scanner.rb +137 -0
  297. data/lib/expressir/express/schema_head_formatter.rb +4 -5
  298. data/lib/expressir/express/schema_plain_source_formatter.rb +11 -0
  299. data/lib/expressir/express/schema_source_formatter.rb +15 -0
  300. data/lib/expressir/express/scope_resolver.rb +223 -0
  301. data/lib/expressir/express/self_schema_reference.rb +126 -0
  302. data/lib/expressir/express/shtolo.rb +679 -0
  303. data/lib/expressir/express/smrl_xml.rb +125 -0
  304. data/lib/expressir/express/source_formatter.rb +15 -0
  305. data/lib/expressir/express/streaming_builder.rb +435 -0
  306. data/lib/expressir/express/xsd.rb +259 -0
  307. data/lib/expressir/express.rb +53 -0
  308. data/lib/expressir/liquid.rb +1 -0
  309. data/lib/expressir/manifest/resolver.rb +210 -0
  310. data/lib/expressir/manifest/validator.rb +192 -0
  311. data/lib/expressir/manifest.rb +6 -0
  312. data/lib/expressir/mapping/refpath.rb +857 -0
  313. data/lib/expressir/mapping.rb +253 -0
  314. data/lib/expressir/model/cache.rb +10 -9
  315. data/lib/expressir/model/concerns.rb +42 -0
  316. data/lib/expressir/model/data_types/aggregate.rb +8 -13
  317. data/lib/expressir/model/data_types/array.rb +15 -21
  318. data/lib/expressir/model/data_types/bag.rb +11 -15
  319. data/lib/expressir/model/data_types/binary.rb +9 -12
  320. data/lib/expressir/model/data_types/boolean.rb +7 -2
  321. data/lib/expressir/model/data_types/enumeration.rb +11 -15
  322. data/lib/expressir/model/data_types/enumeration_item.rb +5 -7
  323. data/lib/expressir/model/data_types/generic.rb +6 -8
  324. data/lib/expressir/model/data_types/generic_entity.rb +11 -13
  325. data/lib/expressir/model/data_types/integer.rb +7 -2
  326. data/lib/expressir/model/data_types/list.rb +13 -18
  327. data/lib/expressir/model/data_types/logical.rb +7 -2
  328. data/lib/expressir/model/data_types/number.rb +7 -2
  329. data/lib/expressir/model/data_types/real.rb +7 -9
  330. data/lib/expressir/model/data_types/select.rb +13 -18
  331. data/lib/expressir/model/data_types/set.rb +11 -15
  332. data/lib/expressir/model/data_types/string.rb +9 -12
  333. data/lib/expressir/model/data_types.rb +25 -0
  334. data/lib/expressir/model/declarations/attribute.rb +19 -28
  335. data/lib/expressir/model/declarations/constant.rb +10 -16
  336. data/lib/expressir/model/declarations/derived_attribute.rb +25 -0
  337. data/lib/expressir/model/declarations/entity.rb +39 -30
  338. data/lib/expressir/model/declarations/function.rb +32 -40
  339. data/lib/expressir/model/declarations/informal_proposition_rule.rb +25 -0
  340. data/lib/expressir/model/declarations/interface.rb +25 -16
  341. data/lib/expressir/model/declarations/interface_item.rb +9 -11
  342. data/lib/expressir/model/declarations/interfaced_item.rb +15 -19
  343. data/lib/expressir/model/declarations/inverse_attribute.rb +25 -0
  344. data/lib/expressir/model/declarations/parameter.rb +10 -16
  345. data/lib/expressir/model/declarations/procedure.rb +30 -37
  346. data/lib/expressir/model/declarations/remark_item.rb +11 -11
  347. data/lib/expressir/model/declarations/rule.rb +38 -43
  348. data/lib/expressir/model/declarations/schema.rb +162 -64
  349. data/lib/expressir/model/declarations/schema_version.rb +8 -11
  350. data/lib/expressir/model/declarations/schema_version_item.rb +8 -11
  351. data/lib/expressir/model/declarations/subtype_constraint.rb +14 -22
  352. data/lib/expressir/model/declarations/type.rb +18 -18
  353. data/lib/expressir/model/declarations/unique_rule.rb +8 -13
  354. data/lib/expressir/model/declarations/variable.rb +10 -16
  355. data/lib/expressir/model/declarations/where_rule.rb +8 -13
  356. data/lib/expressir/model/declarations.rb +31 -0
  357. data/lib/expressir/model/dependency_resolver.rb +268 -0
  358. data/lib/expressir/model/exp_file.rb +42 -0
  359. data/lib/expressir/model/expressions/aggregate_initializer.rb +8 -9
  360. data/lib/expressir/model/expressions/aggregate_initializer_item.rb +10 -12
  361. data/lib/expressir/model/expressions/binary_expression.rb +42 -36
  362. data/lib/expressir/model/expressions/entity_constructor.rb +10 -12
  363. data/lib/expressir/model/expressions/function_call.rb +10 -12
  364. data/lib/expressir/model/expressions/interval.rb +18 -23
  365. data/lib/expressir/model/expressions/query_expression.rb +11 -15
  366. data/lib/expressir/model/expressions/unary_expression.rb +13 -15
  367. data/lib/expressir/model/expressions.rb +18 -0
  368. data/lib/expressir/model/identifier.rb +18 -26
  369. data/lib/expressir/model/indexes/entity_index.rb +103 -0
  370. data/lib/expressir/model/indexes/item_graph.rb +185 -0
  371. data/lib/expressir/model/indexes/reference_index.rb +148 -0
  372. data/lib/expressir/model/indexes/type_index.rb +149 -0
  373. data/lib/expressir/model/indexes.rb +12 -0
  374. data/lib/expressir/model/interface_validator.rb +384 -0
  375. data/lib/expressir/model/literals/binary.rb +7 -9
  376. data/lib/expressir/model/literals/integer.rb +7 -9
  377. data/lib/expressir/model/literals/logical.rb +10 -12
  378. data/lib/expressir/model/literals/real.rb +7 -9
  379. data/lib/expressir/model/literals/string.rb +10 -12
  380. data/lib/expressir/model/literals.rb +13 -0
  381. data/lib/expressir/model/model_element.rb +286 -117
  382. data/lib/expressir/model/references/attribute_reference.rb +9 -12
  383. data/lib/expressir/model/references/group_reference.rb +9 -12
  384. data/lib/expressir/model/references/index_reference.rb +11 -15
  385. data/lib/expressir/model/references/simple_reference.rb +11 -14
  386. data/lib/expressir/model/references.rb +12 -0
  387. data/lib/expressir/model/remark_format.rb +17 -0
  388. data/lib/expressir/model/remark_info.rb +92 -0
  389. data/lib/expressir/model/remark_placement.rb +42 -0
  390. data/lib/expressir/model/repository.rb +472 -12
  391. data/lib/expressir/model/repository_validator.rb +293 -0
  392. data/lib/expressir/model/search_engine.rb +551 -0
  393. data/lib/expressir/model/statements/alias.rb +12 -16
  394. data/lib/expressir/model/statements/assignment.rb +12 -11
  395. data/lib/expressir/model/statements/case.rb +31 -14
  396. data/lib/expressir/model/statements/case_action.rb +9 -11
  397. data/lib/expressir/model/statements/compound.rb +10 -8
  398. data/lib/expressir/model/statements/escape.rb +10 -2
  399. data/lib/expressir/model/statements/if.rb +15 -14
  400. data/lib/expressir/model/statements/null.rb +10 -2
  401. data/lib/expressir/model/statements/procedure_call.rb +11 -11
  402. data/lib/expressir/model/statements/repeat.rb +21 -28
  403. data/lib/expressir/model/statements/return.rb +9 -8
  404. data/lib/expressir/model/statements/skip.rb +10 -2
  405. data/lib/expressir/model/statements.rb +20 -0
  406. data/lib/expressir/model/supertype_expressions/binary_supertype_expression.rb +13 -17
  407. data/lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb +7 -9
  408. data/lib/expressir/model/supertype_expressions.rb +12 -0
  409. data/lib/expressir/model.rb +38 -78
  410. data/lib/expressir/package/builder.rb +231 -0
  411. data/lib/expressir/package/metadata.rb +79 -0
  412. data/lib/expressir/package/reader.rb +149 -0
  413. data/lib/expressir/package.rb +8 -0
  414. data/lib/expressir/schema_manifest.rb +159 -0
  415. data/lib/expressir/schema_manifest_entry.rb +15 -0
  416. data/lib/expressir/version.rb +6 -1
  417. data/lib/expressir.rb +79 -9
  418. data/lib/tasks/verify_remarks.rake +16 -0
  419. data/rakelib/native.rake +24 -0
  420. data/rakelib/oracle.rake +52 -0
  421. data/rakelib/verify_remarks.rake +16 -0
  422. metadata +431 -129
  423. data/.cross_rubies +0 -20
  424. data/.gitmodules +0 -6
  425. data/.yardopts +0 -11
  426. data/docs/development.md +0 -90
  427. data/exe/format +0 -18
  428. data/exe/generate-parser +0 -51
  429. data/lib/expressir/cli/ui.rb +0 -36
  430. data/lib/expressir/express/2.7/express_parser.so +0 -0
  431. data/lib/expressir/express/3.0/express_parser.so +0 -0
  432. data/lib/expressir/express/3.1/express_parser.so +0 -0
  433. data/lib/expressir/express/3.2/express_parser.so +0 -0
  434. data/lib/expressir/express/visitor.rb +0 -2588
  435. data/lib/expressir/model/data_type.rb +0 -9
  436. data/lib/expressir/model/declaration.rb +0 -9
  437. data/lib/expressir/model/expression.rb +0 -9
  438. data/lib/expressir/model/literal.rb +0 -9
  439. data/lib/expressir/model/reference.rb +0 -9
  440. data/lib/expressir/model/statement.rb +0 -9
  441. data/lib/expressir/model/supertype_expression.rb +0 -9
  442. data/rakelib/antlr4-native.rake +0 -161
  443. data/rakelib/cross-ruby.rake +0 -368
  444. data/spec/acceptance/version_spec.rb +0 -27
  445. data/spec/expressir/express/cache_spec.rb +0 -89
  446. data/spec/expressir/express/formatter_spec.rb +0 -173
  447. data/spec/expressir/express/parser_spec.rb +0 -141
  448. data/spec/expressir/model/model_element_spec.rb +0 -318
  449. data/spec/spec_helper.rb +0 -24
  450. data/spec/support/console_helper.rb +0 -29
  451. data/spec/syntax/multiple.exp +0 -23
  452. data/spec/syntax/multiple.yaml +0 -198
  453. data/spec/syntax/multiple_formatted.exp +0 -71
  454. data/spec/syntax/multiple_hyperlink_formatted.exp +0 -71
  455. data/spec/syntax/multiple_schema_head_hyperlink_formatted.exp +0 -13
  456. data/spec/syntax/remark.exp +0 -193
  457. data/spec/syntax/remark.yaml +0 -471
  458. data/spec/syntax/remark_formatted.exp +0 -228
  459. data/spec/syntax/single.exp +0 -4
  460. data/spec/syntax/single.yaml +0 -18
  461. data/spec/syntax/single_formatted.exp +0 -10
  462. data/spec/syntax/single_formatted.yaml +0 -36
  463. data/spec/syntax/syntax.exp +0 -333
  464. data/spec/syntax/syntax.yaml +0 -3509
  465. data/spec/syntax/syntax_formatted.exp +0 -902
  466. data/spec/syntax/syntax_hyperlink_formatted.exp +0 -902
  467. data/spec/syntax/syntax_schema_head_formatted.exp +0 -18
@@ -0,0 +1,259 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ # EXPRESS → XML Schema writer (expressir #276 step 2,
6
+ # TODO.parity-ee 15) — the express2xsd counterpart, built on
7
+ # moxml.
8
+ #
9
+ # Mapping (v2):
10
+ # ENTITY → xs:element + xs:complexType (explicit attributes
11
+ # in declaration order); SUBTYPE OF a schema-local
12
+ # entity becomes a substitutionGroup reference.
13
+ # ENUMERATION → xs:simpleType with enumeration facets.
14
+ # SELECT → xs:complexType with an xs:choice over the member
15
+ # types (ISO 10303-28 select mapping): entity
16
+ # members reference their global element
17
+ # declarations, defined-type members carry their
18
+ # simpleType. Declared members only — extensible
19
+ # selects and cross-schema members keep the
20
+ # documented v1 fallbacks.
21
+ # defined TYPE over a simple type → xs:simpleType restriction.
22
+ # attributes → xs:element inside the complexType sequence;
23
+ # LIST/SET/BAG/ARRAY → maxOccurs="unbounded".
24
+ #
25
+ # Built-in EXPRESS types map to XML Schema built-ins (STRING→
26
+ # xs:string, INTEGER→xs:integer, REAL/NUMBER→xs:double,
27
+ # BOOLEAN→xs:boolean, LOGICAL→string restriction, BINARY→
28
+ # xs:hexBinary).
29
+ module Xsd
30
+ BUILTIN_TYPES = {
31
+ "string" => "xs:string",
32
+ "integer" => "xs:integer",
33
+ "real" => "xs:double",
34
+ "number" => "xs:double",
35
+ "boolean" => "xs:boolean",
36
+ "binary" => "xs:hexBinary",
37
+ }.freeze
38
+
39
+ AGGREGATES = %w[array list set bag].freeze
40
+
41
+ module_function
42
+
43
+ # @param schema [Model::Declarations::Schema]
44
+ # @return [String] the serialized xs:schema document
45
+ def format(schema)
46
+ ctx = Moxml::Context.new
47
+ doc = ctx.create_document
48
+ root = doc.create_element("xs:schema")
49
+ root.set_attributes("xmlns:xs" => "http://www.w3.org/2001/XMLSchema",
50
+ "elementFormDefault" => "qualified")
51
+ doc.add_child(root)
52
+ schema.types.to_a.each { |type| root.add_child(type_node(doc, schema, type)) }
53
+ schema.entities.to_a.each do |entity|
54
+ root.add_child(entity_element(doc, schema, entity))
55
+ root.add_child(entity_type(doc, schema, entity))
56
+ end
57
+ doc.to_xml
58
+ end
59
+
60
+ def type_node(doc, schema, type)
61
+ underlying = type.underlying_type
62
+ if underlying.is_a?(Expressir::Model::DataTypes::Select)
63
+ return select_type_node(doc, schema, type, underlying)
64
+ end
65
+
66
+ node = doc.create_element("xs:simpleType")
67
+ node.set_attributes("name" => type.id)
68
+ restriction = doc.create_element("xs:restriction")
69
+ node.add_child(restriction)
70
+ if underlying.is_a?(Expressir::Model::DataTypes::Enumeration)
71
+ restriction.set_attributes("base" => "xs:string")
72
+ underlying.items.to_a.each do |item|
73
+ facet = doc.create_element("xs:enumeration")
74
+ facet.set_attributes("value" => item.id)
75
+ restriction.add_child(facet)
76
+ end
77
+ else
78
+ restriction.set_attributes("base" => xs_type(underlying, schema))
79
+ end
80
+ node
81
+ end
82
+
83
+ # ISO 10303-28: a select type maps to a complexType choosing
84
+ # among its member types. An extensible select with no declared
85
+ # items gets an empty sequence — an empty xs:choice is not
86
+ # schema-valid.
87
+ def select_type_node(doc, schema, type, select)
88
+ node = doc.create_element("xs:complexType")
89
+ node.set_attributes("name" => type.id)
90
+ container = select.items.to_a.empty? ? "xs:sequence" : "xs:choice"
91
+ choice = doc.create_element(container)
92
+ node.add_child(choice)
93
+ select.items.to_a.each do |item|
94
+ choice.add_child(select_member_element(doc, schema, item))
95
+ end
96
+ node
97
+ end
98
+
99
+ def select_member_element(doc, schema, item)
100
+ node = doc.create_element("xs:element")
101
+ if item.is_a?(Expressir::Model::References::SimpleReference)
102
+ id = item.respond_to?(:base_path) && item.base_path ? base_id(item.base_path) : item.id
103
+ member = select_member_target(schema, id)
104
+ if member == :entity
105
+ node.set_attributes("ref" => id)
106
+ elsif member == :type
107
+ node.set_attributes("name" => id, "type" => id)
108
+ else
109
+ node.set_attributes("name" => id, "type" => "xs:anyType")
110
+ end
111
+ else
112
+ name = item.class.name.split("::").last.downcase
113
+ node.set_attributes("name" => name,
114
+ "type" => BUILTIN_TYPES.fetch(name, "xs:anyType"))
115
+ end
116
+ node
117
+ end
118
+
119
+ def select_member_target(schema, id)
120
+ if schema.entities.to_a.any? { |e| e.id.safe_downcase == id.safe_downcase }
121
+ :entity
122
+ elsif schema.types.to_a.any? { |t| t.id.safe_downcase == id.safe_downcase }
123
+ :type
124
+ else
125
+ :unknown
126
+ end
127
+ end
128
+
129
+ def entity_element(doc, schema, entity)
130
+ node = doc.create_element("xs:element")
131
+ node.set_attributes("name" => entity.id)
132
+ node.set_attributes("type" => entity.id)
133
+ parent = supertype_name(schema, entity)
134
+ node.set_attributes("substitutionGroup" => parent) if parent
135
+ node
136
+ end
137
+
138
+ def entity_type(doc, schema, entity)
139
+ node = doc.create_element("xs:complexType")
140
+ node.set_attributes("name" => entity.id)
141
+ container = node
142
+ parent = supertype_name(schema, entity)
143
+ if parent
144
+ content = doc.create_element("xs:complexContent")
145
+ extension = doc.create_element("xs:extension")
146
+ extension.set_attributes("base" => parent)
147
+ content.add_child(extension)
148
+ node.add_child(content)
149
+ container = extension
150
+ end
151
+ sequence = doc.create_element("xs:sequence")
152
+ container.add_child(sequence)
153
+ explicit_attributes(entity).each do |attr|
154
+ sequence.add_child(attribute_element(doc, schema, attr))
155
+ end
156
+ # EXPRESS multiple inheritance: the extension base carries the
157
+ # first parent's chain; later parents' attributes (transitively)
158
+ # become explicit members of the subtype's sequence.
159
+ additional_parent_attributes(schema, entity).each do |attr|
160
+ sequence.add_child(attribute_element(doc, schema, attr))
161
+ end
162
+ node
163
+ end
164
+
165
+ def explicit_attributes(entity)
166
+ entity.attributes.to_a.reject do |attr|
167
+ attr.kind == Expressir::Model::Declarations::Attribute::INVERSE ||
168
+ (attr.respond_to?(:derive?) && attr.derive?)
169
+ end
170
+ end
171
+
172
+ # Attributes contributed by multiple inheritance: every ancestor
173
+ # reachable from the additional local supertypes (all but the
174
+ # first), minus the first supertype's own chain — the extension
175
+ # base already carries that. Cycle-safe.
176
+ def additional_parent_attributes(schema, entity)
177
+ parents = local_supertypes(schema, entity)
178
+ return [] if parents.size <= 1
179
+
180
+ base_chain = ancestor_set(schema, parents.first)
181
+ seen = {}.compare_by_identity
182
+ queue = parents.drop(1)
183
+ attrs = []
184
+ until queue.empty?
185
+ current = queue.shift
186
+ next if seen[current] || base_chain[current]
187
+
188
+ seen[current] = true
189
+ attrs.concat(explicit_attributes(current))
190
+ queue.concat(local_supertypes(schema, current))
191
+ end
192
+ attrs
193
+ end
194
+
195
+ # Identity set of +entity+ and every supertype ancestor.
196
+ def ancestor_set(schema, entity)
197
+ seen = {}.compare_by_identity
198
+ queue = [entity]
199
+ until queue.empty?
200
+ current = queue.shift
201
+ next if seen[current]
202
+
203
+ seen[current] = true
204
+ queue.concat(local_supertypes(schema, current))
205
+ end
206
+ seen
207
+ end
208
+
209
+ def local_supertypes(schema, entity)
210
+ Array(entity.subtype_of).filter_map do |ref|
211
+ id = ref.is_a?(String) ? ref : ref.id
212
+ next nil unless id
213
+
214
+ schema.entities.to_a
215
+ .find { |e| e.id.safe_downcase == id.safe_downcase }
216
+ end
217
+ end
218
+
219
+ def attribute_element(doc, schema, attr)
220
+ node = doc.create_element("xs:element")
221
+ node.set_attributes("name" => attr.id)
222
+ node.set_attributes("type" => xs_type(attr.type, schema))
223
+ kind = attr.type.class.name.split("::").last.downcase
224
+ node.set_attributes("maxOccurs" => "unbounded") if AGGREGATES.include?(kind)
225
+ node
226
+ end
227
+
228
+ def xs_type(type, schema)
229
+ if type.is_a?(Expressir::Model::References::SimpleReference)
230
+ id = type.respond_to?(:base_path) && type.base_path ? base_id(type.base_path) : type.id
231
+ return schema.types.to_a.any? { |t| t.id.safe_downcase == id.safe_downcase } ? id : "xs:anyType"
232
+ end
233
+
234
+ if type.is_a?(Expressir::Model::DataTypes::Enumeration)
235
+ return type.id || "xs:string"
236
+ end
237
+
238
+ if type.respond_to?(:base_type)
239
+ inner = type.base_type
240
+ return xs_type(inner, schema) if inner
241
+
242
+ return "xs:anyType"
243
+ end
244
+
245
+ name = type.class.name.split("::").last.downcase
246
+ BUILTIN_TYPES.fetch(name, "xs:anyType")
247
+ end
248
+
249
+ def supertype_name(schema, entity)
250
+ local_supertypes(schema, entity).first&.id
251
+ end
252
+
253
+ def base_id(base_path)
254
+ parts = base_path.split(".")
255
+ parts[-1]
256
+ end
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ autoload :AstKeyConverter, "#{__dir__}/express/ast_key_converter"
6
+ autoload :Builder, "#{__dir__}/express/builder"
7
+ autoload :BuilderContext, "#{__dir__}/express/builder_context"
8
+ autoload :BuilderRegistry, "#{__dir__}/express/builder_registry"
9
+ autoload :Builders, "#{__dir__}/express/builders"
10
+
11
+ # Core classes (autoloaded for lazy loading)
12
+ autoload :Cache, "#{__dir__}/express/cache"
13
+ autoload :AdocHyperlinkFormatter, "#{__dir__}/express/adoc_hyperlink_formatter"
14
+ autoload :AdocSourceFormatter, "#{__dir__}/express/adoc_source_formatter"
15
+ autoload :Checker, "#{__dir__}/express/checker"
16
+ autoload :Concatenator, "#{__dir__}/express/concatenator"
17
+ autoload :Core, "#{__dir__}/express/core"
18
+ autoload :RemarkOverlay, "#{__dir__}/express/remark_overlay"
19
+ autoload :ModelTraversal, "#{__dir__}/express/model_traversal"
20
+ autoload :RefsOverlay, "#{__dir__}/express/refs_overlay"
21
+ autoload :Error, "#{__dir__}/express/error"
22
+ autoload :Formatter, "#{__dir__}/express/formatter"
23
+ autoload :Formatters, "#{__dir__}/express/formatters"
24
+ autoload :Grammar, "#{__dir__}/express/grammar"
25
+ autoload :HyperlinkFormatter, "#{__dir__}/express/hyperlink_formatter"
26
+ autoload :InterfaceDot, "#{__dir__}/express/interface_dot"
27
+ autoload :LineMap, "#{__dir__}/express/line_map"
28
+ autoload :Listing, "#{__dir__}/express/listing"
29
+ autoload :ModelVisitor, "#{__dir__}/express/model_visitor"
30
+ autoload :NodePositionIndex, "#{__dir__}/express/node_position_index"
31
+ autoload :ParallelFiles, "#{__dir__}/express/parallel_files"
32
+ autoload :Parser, "#{__dir__}/express/parser"
33
+ autoload :PrettyFormatter, "#{__dir__}/express/pretty_formatter"
34
+ autoload :PrettyGate, "#{__dir__}/express/pretty_gate"
35
+ autoload :RemarkAttacher, "#{__dir__}/express/remark_attacher"
36
+ autoload :RemarkScanner, "#{__dir__}/express/remark_scanner"
37
+ autoload :ResolveReferencesModelVisitor,
38
+ "#{__dir__}/express/resolve_references_model_visitor"
39
+ autoload :SelfSchemaReference, "#{__dir__}/express/self_schema_reference"
40
+ autoload :Shtolo, "#{__dir__}/express/shtolo"
41
+ autoload :SchemaBlockScanner, "#{__dir__}/express/schema_block_scanner"
42
+ autoload :SchemaHeadFormatter, "#{__dir__}/express/schema_head_formatter"
43
+ autoload :SchemaPlainSourceFormatter,
44
+ "#{__dir__}/express/schema_plain_source_formatter"
45
+ autoload :SchemaSourceFormatter, "#{__dir__}/express/schema_source_formatter"
46
+ autoload :ScopeResolver, "#{__dir__}/express/scope_resolver"
47
+ autoload :LazyRepository, "#{__dir__}/express/lazy_repository"
48
+ autoload :SmrlXml, "#{__dir__}/express/smrl_xml"
49
+ autoload :Xsd, "#{__dir__}/express/xsd"
50
+ autoload :SourceFormatter, "#{__dir__}/express/source_formatter"
51
+ autoload :StreamingBuilder, "#{__dir__}/express/streaming_builder"
52
+ end
53
+ end
@@ -0,0 +1 @@
1
+ require "liquid"
@@ -0,0 +1,210 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Manifest
5
+ # Resolves schema paths in manifests using pattern-based path discovery
6
+ # Attempts to find file paths for schemas with missing or empty paths
7
+ class Resolver
8
+ attr_reader :manifest, :options, :base_dirs
9
+
10
+ # Initialize resolver
11
+ # @param manifest [SchemaManifest] The manifest to resolve
12
+ # @param options [Hash] Resolution options
13
+ # @option options [Array<String>] :base_dirs Base directories to search
14
+ # @option options [Boolean] :verbose Enable verbose output
15
+ def initialize(manifest, options = {})
16
+ @manifest = manifest
17
+ @options = options
18
+ @base_dirs = extract_base_dirs_from_manifest
19
+
20
+ # Override with explicit base_dirs if provided
21
+ if options[:base_dirs]
22
+ @base_dirs = Array(options[:base_dirs]).map do |d|
23
+ File.expand_path(d)
24
+ end
25
+ end
26
+ end
27
+
28
+ # Resolve paths for all schemas in manifest
29
+ # Works like manifest create - resolves all dependencies from schemas with paths
30
+ # @return [SchemaManifest] New manifest with resolved paths and dependencies
31
+ def resolve_paths
32
+ # Create new manifest to avoid modifying original
33
+ resolved_manifest = SchemaManifest.new
34
+
35
+ # Track all resolved schema paths
36
+ all_resolved_paths = Set.new
37
+ all_unresolved = []
38
+
39
+ # Find schemas with valid paths to use as roots
40
+ root_schemas = manifest.schemas.select do |s|
41
+ !s.path.nil? && !s.path.empty? && File.exist?(s.path)
42
+ end
43
+
44
+ if root_schemas.empty?
45
+ # No roots, just try to resolve individual schemas
46
+ say "No valid schema paths found, attempting simple path resolution..." if options[:verbose]
47
+ return resolve_paths_simple
48
+ end
49
+
50
+ say "Resolving dependencies from #{root_schemas.size} root schema(s)..." if options[:verbose]
51
+ say_base_dirs
52
+
53
+ # For each root schema, resolve all its dependencies
54
+ root_schemas.each do |root_entry|
55
+ resolver = Model::DependencyResolver.new(
56
+ base_dirs: @base_dirs,
57
+ schema_registry: build_schema_registry,
58
+ verbose: options[:verbose],
59
+ )
60
+
61
+ # Resolve all dependencies for this root
62
+ resolved_paths = resolver.resolve_dependencies(root_entry.path)
63
+ all_resolved_paths.merge(resolved_paths)
64
+ all_unresolved.concat(resolver.unresolved)
65
+ end
66
+
67
+ # Add all resolved schemas to manifest
68
+ all_resolved_paths.each do |path|
69
+ schema_id = extract_schema_name(path)
70
+ resolved_manifest.schemas << SchemaManifestEntry.new(
71
+ id: schema_id,
72
+ path: path,
73
+ )
74
+ end
75
+
76
+ # Add unresolved schemas with empty paths
77
+ all_unresolved.uniq { |e| e[:schema_name] }.each do |entry|
78
+ # Only add if not already in manifest
79
+ unless resolved_manifest.schemas.any? do |s|
80
+ s.id == entry[:schema_name]
81
+ end
82
+ resolved_manifest.schemas << SchemaManifestEntry.new(
83
+ id: entry[:schema_name],
84
+ path: "",
85
+ )
86
+ end
87
+ end
88
+
89
+ resolved_manifest
90
+ end
91
+
92
+ # Simple path resolution - just try to find missing paths
93
+ # Used when no valid root schemas are available
94
+ # @return [SchemaManifest] New manifest with resolved paths
95
+ def resolve_paths_simple
96
+ resolved_manifest = SchemaManifest.new
97
+
98
+ resolver = Model::DependencyResolver.new(
99
+ base_dirs: @base_dirs,
100
+ schema_registry: build_schema_registry,
101
+ verbose: options[:verbose],
102
+ )
103
+
104
+ manifest.schemas.each do |schema_entry|
105
+ resolved_entry = resolve_schema_entry(schema_entry, resolver)
106
+ resolved_manifest.schemas << resolved_entry
107
+ end
108
+
109
+ resolved_manifest
110
+ end
111
+
112
+ # Get resolution statistics
113
+ # @return [Hash] Resolution statistics
114
+ def statistics
115
+ unresolved_count = manifest.schemas.count do |s|
116
+ s.path.nil? || s.path.empty?
117
+ end
118
+ {
119
+ total_schemas: manifest.schemas.size,
120
+ resolved: manifest.schemas.size - unresolved_count,
121
+ unresolved: unresolved_count,
122
+ base_dirs: @base_dirs,
123
+ }
124
+ end
125
+
126
+ private
127
+
128
+ # Extract the actual schema name from a schema file by parsing it
129
+ # @param schema_path [String] Path to the schema file
130
+ # @return [String] The schema name declared in the file
131
+ def extract_schema_name(schema_path)
132
+ repo = Expressir::Express::Parser.from_file(schema_path)
133
+ schema = repo.schemas.first
134
+ schema&.id || File.basename(schema_path, ".*")
135
+ rescue StandardError
136
+ # Fallback to filename if parsing fails
137
+ File.basename(schema_path, ".*")
138
+ end
139
+
140
+ # Say message (only used when verbose is enabled)
141
+ def say(message)
142
+ puts message if options[:verbose]
143
+ end
144
+
145
+ # Say base directories with numbered labels
146
+ def say_base_dirs
147
+ if options[:verbose] && @base_dirs
148
+ say " Using base directories:"
149
+ @base_dirs.each_with_index do |dir, index|
150
+ say " - [source #{index + 1}]: #{dir}"
151
+ end
152
+ end
153
+ end
154
+
155
+ # Resolve a single schema entry
156
+ # @param schema_entry [SchemaManifestEntry] The entry to resolve
157
+ # @param resolver [Model::DependencyResolver] The resolver to use
158
+ # @return [SchemaManifestEntry] New entry with resolved path
159
+ def resolve_schema_entry(schema_entry, resolver)
160
+ # If path already exists and is valid, keep it
161
+ if schema_entry.path && !schema_entry.path.empty? && File.exist?(schema_entry.path)
162
+ return SchemaManifestEntry.new(
163
+ id: schema_entry.id,
164
+ path: schema_entry.path,
165
+ )
166
+ end
167
+
168
+ # Try to resolve path using DependencyResolver
169
+ resolved_path = resolver.resolve_schema_location(
170
+ schema_entry.id,
171
+ "USE", # Kind doesn't matter for location resolution
172
+ nil, # No current path context
173
+ )
174
+
175
+ SchemaManifestEntry.new(
176
+ id: schema_entry.id,
177
+ path: resolved_path || schema_entry.path || "",
178
+ )
179
+ end
180
+
181
+ # Build schema registry from manifest entries with valid paths
182
+ # Maps schema IDs to their file paths
183
+ # @return [Hash<String, String>] Schema name => path mapping
184
+ def build_schema_registry
185
+ registry = {}
186
+ manifest.schemas.each do |schema_entry|
187
+ next if schema_entry.id.nil?
188
+ next if schema_entry.path.nil? || schema_entry.path.empty?
189
+ next unless File.exist?(schema_entry.path)
190
+
191
+ registry[schema_entry.id] = schema_entry.path
192
+ end
193
+ registry
194
+ end
195
+
196
+ # Extract base directories from manifest schema paths
197
+ # @return [Array<String>] List of unique base directories
198
+ def extract_base_dirs_from_manifest
199
+ dirs = manifest.schemas
200
+ .reject { |s| s.path.nil? || s.path.empty? }
201
+ .select { |s| File.exist?(s.path) }
202
+ .map { |s| File.dirname(File.expand_path(s.path)) }
203
+ .uniq
204
+
205
+ # If no directories found, use current directory
206
+ dirs.empty? ? [Dir.pwd] : dirs
207
+ end
208
+ end
209
+ end
210
+ end