expressir 2.4.29-arm-linux-musl

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 (426) hide show
  1. checksums.yaml +7 -0
  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 +19 -0
  9. data/.github/workflows/release.yml +37 -0
  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 +55 -0
  15. data/.hound.yml +3 -0
  16. data/.rspec +2 -0
  17. data/.rubocop.yml +18 -0
  18. data/.rubocop_todo.yml +297 -0
  19. data/CHANGELOG.md +159 -0
  20. data/Gemfile +18 -0
  21. data/README.adoc +2783 -0
  22. data/Rakefile +41 -0
  23. data/TODO.bugs/01-stale-transformer-autoload.md +39 -0
  24. data/TODO.bugs/02-parser-class-instance-vars.md +36 -0
  25. data/TODO.bugs/03-builder-mutable-state.md +43 -0
  26. data/TODO.bugs/04-formatter-public-send-dispatch.md +53 -0
  27. data/TODO.bugs/05-anonymous-formatter-subclass.md +45 -0
  28. data/TODO.bugs/06-collection-registry-single-source.md +53 -0
  29. data/TODO.bugs/07-require-relative-cleanup.md +42 -0
  30. data/TODO.bugs/08-require-expressir-in-commands.md +34 -0
  31. data/TODO.bugs/09-parser-split.md +53 -0
  32. data/TODO.bugs/10-to-s-override.md +42 -0
  33. data/TODO.bugs/11-parser-class-variables.md +39 -0
  34. data/TODO.bugs/12-marker-modules-vs-registry.md +64 -0
  35. data/TODO.bugs/13-string-literal-scanner-limitation.md +52 -0
  36. data/TODO.bugs/14-model-formatting-leak.md +30 -0
  37. data/TODO.bugs/15-expression-children-macro.md +27 -0
  38. data/TODO.bugs/16-pretty-formatter-duplication.md +28 -0
  39. data/TODO.bugs/17-snake-case-cache-mutable-constant.md +28 -0
  40. data/TODO.bugs/18-const-get-private-constants.md +30 -0
  41. data/TODO.bugs/19-format-methods-public.md +22 -0
  42. data/TODO.bugs/20-coverage-nested-entities-dedup.md +20 -0
  43. data/TODO.bugs/21-operator-tokens-secondary-dispatch.md +21 -0
  44. data/TODO.bugs/22-builder-fast-path-wrappers.md +32 -0
  45. data/TODO.bugs/23-coverage-inverse-maps.md +21 -0
  46. data/TODO.bugs/24-streaming-builder-complexity.md +19 -0
  47. data/TODO.bugs/25-debug-puts-in-production.md +21 -0
  48. data/TODO.bugs/26-generic-entity-children-misplaced.md +21 -0
  49. data/TODO.bugs/27-package-build-god-method.md +19 -0
  50. data/TODO.bugs/28-package-god-class.md +30 -0
  51. data/TODO.bugs/29-validate-ascii-god-class.md +24 -0
  52. data/TODO.bugs/30-unicode-map-extraction.md +19 -0
  53. data/TODO.bugs/README.md +43 -0
  54. data/TODO.max-perf/01-restore-ci-green.md +36 -0
  55. data/TODO.max-perf/02-streaming-parse-path.md +31 -0
  56. data/TODO.max-perf/03-cli-parallel-opt-in.md +27 -0
  57. data/TODO.max-perf/04-benchmark-harness.md +28 -0
  58. data/TODO.max-perf/05-parallel-fidelity-specs.md +22 -0
  59. data/TODO.max-perf/06-builder-cpu-audit.md +41 -0
  60. data/TODO.max-perf/07-upstream-parsanol-roadmap.md +27 -0
  61. data/TODO.max-perf/08-builder-build-perf.md +45 -0
  62. data/TODO.max-perf/09-grammar-cold-start.md +25 -0
  63. data/TODO.max-perf/10-parser-facade-hygiene.md +23 -0
  64. data/TODO.max-perf/11-ci-green-closeout.md +25 -0
  65. data/TODO.max-perf/12-require-boot-profile.md +25 -0
  66. data/TODO.max-perf/13-key-conversion-specs.md +26 -0
  67. data/TODO.max-perf/14-builder-call-handler-audit.md +28 -0
  68. data/TODO.parity-ee/00-overview.md +76 -0
  69. data/TODO.parity-ee/01-annex-g-rule-extraction.md +41 -0
  70. data/TODO.parity-ee/02-eeng-algorithm-inventory.md +8 -0
  71. data/TODO.parity-ee/03-eeng-oracle-harness.md +33 -0
  72. data/TODO.parity-ee/04-shtolo-concatenate.md +44 -0
  73. data/TODO.parity-ee/05-shtolo-longform-flatten.md +53 -0
  74. data/TODO.parity-ee/06-interface-scheduling-parity.md +47 -0
  75. data/TODO.parity-ee/07-semantic-checks-port.md +35 -0
  76. data/TODO.parity-ee/08-pretty-roundtrip-gate.md +27 -0
  77. data/TODO.parity-ee/09-smrl-index-and-listing.md +22 -0
  78. data/TODO.parity-ee/10-interface-dot-graph.md +21 -0
  79. data/TODO.parity-ee/11-import-eeng-tests.md +79 -0
  80. data/TODO.parity-ee/12-full-check-catalog.md +67 -0
  81. data/TODO.parity-ee/13-population-p21.md +54 -0
  82. data/TODO.parity-ee/14-shtolo-completion.md +44 -0
  83. data/TODO.parity-ee/15-part28-xml.md +51 -0
  84. data/TODO.parity-ee/16-compare-patch.md +48 -0
  85. data/TODO.parity-ee/17-official-tests.md +42 -0
  86. data/TODO.parity-ee/18-mim-mapping.md +47 -0
  87. data/TODO.parity-ee/19-architecture.md +97 -0
  88. data/TODO.parity-ee/parity-matrix.md +108 -0
  89. data/TODO.refpath-v2/00-overview.md +64 -0
  90. data/TODO.suma-improvements/00-overview.md +23 -0
  91. data/TODO.suma-improvements/01-prebuilt-platform-gems.md +33 -0
  92. data/TODO.suma-improvements/02-suma-e2e.md +39 -0
  93. data/TODO.suma-improvements/03-item-graph.md +22 -0
  94. data/TODO.suma-improvements/04-compiled-set-default.md +16 -0
  95. data/TODO.suma-improvements/05-validation-in-docs.md +17 -0
  96. data/TODO.suma-improvements/06-memory-remeasure.md +36 -0
  97. data/TODO.suma-improvements/07-part28-xml.md +15 -0
  98. data/TODO.suma-improvements/08-windows-gnu-toolchain.md +15 -0
  99. data/TODO.suma-improvements/09-checker-tranche3.md +13 -0
  100. data/TODO.suma-improvements/10-expressdoc.md +8 -0
  101. data/benchmark/srl_benchmark.rb +458 -0
  102. data/benchmark/srl_native_benchmark.rb +146 -0
  103. data/benchmark/srl_ruby_benchmark.rb +132 -0
  104. data/bin/console +11 -0
  105. data/bin/rspec +30 -0
  106. data/bin/setup +8 -0
  107. data/docs/Gemfile +12 -0
  108. data/docs/_config.yml +141 -0
  109. data/docs/_guides/changes/changes-format.adoc +778 -0
  110. data/docs/_guides/changes/importing-eengine.adoc +898 -0
  111. data/docs/_guides/changes/index.adoc +396 -0
  112. data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
  113. data/docs/_guides/changes/validating-changes.adoc +681 -0
  114. data/docs/_guides/cli/benchmark-performance.adoc +834 -0
  115. data/docs/_guides/cli/coverage-analysis.adoc +921 -0
  116. data/docs/_guides/cli/format-schemas.adoc +547 -0
  117. data/docs/_guides/cli/index.adoc +8 -0
  118. data/docs/_guides/cli/managing-changes.adoc +927 -0
  119. data/docs/_guides/cli/validate-ascii.adoc +645 -0
  120. data/docs/_guides/cli/validate-schemas.adoc +534 -0
  121. data/docs/_guides/formatter/formatter-architecture.adoc +401 -0
  122. data/docs/_guides/index.adoc +165 -0
  123. data/docs/_guides/ler/creating-packages.adoc +664 -0
  124. data/docs/_guides/ler/index.adoc +305 -0
  125. data/docs/_guides/ler/loading-packages.adoc +707 -0
  126. data/docs/_guides/ler/package-formats.adoc +748 -0
  127. data/docs/_guides/ler/querying-packages.adoc +826 -0
  128. data/docs/_guides/ler/step-packages.adoc +385 -0
  129. data/docs/_guides/ler/validating-packages.adoc +750 -0
  130. data/docs/_guides/liquid/basic-templates.adoc +813 -0
  131. data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
  132. data/docs/_guides/liquid/drops-reference.adoc +829 -0
  133. data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
  134. data/docs/_guides/liquid/index.adoc +468 -0
  135. data/docs/_guides/manifests/creating-manifests.adoc +483 -0
  136. data/docs/_guides/manifests/index.adoc +307 -0
  137. data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
  138. data/docs/_guides/manifests/validating-manifests.adoc +713 -0
  139. data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
  140. data/docs/_guides/ruby-api/index.adoc +257 -0
  141. data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
  142. data/docs/_guides/ruby-api/search-engine.adoc +609 -0
  143. data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
  144. data/docs/_pages/data-model.adoc +665 -0
  145. data/docs/_pages/express-language.adoc +506 -0
  146. data/docs/_pages/getting-started.adoc +414 -0
  147. data/docs/_pages/index.adoc +116 -0
  148. data/docs/_pages/introduction.adoc +256 -0
  149. data/docs/_pages/ler-packages.adoc +837 -0
  150. data/docs/_pages/parsers.adoc +709 -0
  151. data/docs/_pages/schema-manifests.adoc +431 -0
  152. data/docs/_references/index.adoc +228 -0
  153. data/docs/_tutorials/creating-ler-package.adoc +735 -0
  154. data/docs/_tutorials/documentation-coverage.adoc +795 -0
  155. data/docs/_tutorials/formatting-schemas.adoc +89 -0
  156. data/docs/_tutorials/index.adoc +231 -0
  157. data/docs/_tutorials/liquid-templates.adoc +806 -0
  158. data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
  159. data/docs/_tutorials/querying-schemas.adoc +751 -0
  160. data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
  161. data/docs/index.adoc +242 -0
  162. data/docs/lychee.toml +90 -0
  163. data/examples/demo_ler_usage.sh +86 -0
  164. data/examples/ler/README.md +111 -0
  165. data/examples/ler/simple_example.ler +0 -0
  166. data/examples/ler/simple_schema.exp +33 -0
  167. data/examples/ler_build.rb +75 -0
  168. data/examples/ler_cli.rb +79 -0
  169. data/examples/ler_demo_complete.rb +276 -0
  170. data/examples/ler_query.rb +91 -0
  171. data/examples/ler_query_examples.rb +305 -0
  172. data/examples/ler_stats.rb +81 -0
  173. data/examples/phase3_demo.rb +159 -0
  174. data/examples/query_demo_simple.rb +131 -0
  175. data/exe/expressir +11 -0
  176. data/exe/expressir-format +14 -0
  177. data/exe/expressir-format-test +82 -0
  178. data/expressir.gemspec +61 -0
  179. data/lib/expressir/3.2/expressir_core.so +0 -0
  180. data/lib/expressir/3.3/expressir_core.so +0 -0
  181. data/lib/expressir/3.4/expressir_core.so +0 -0
  182. data/lib/expressir/4.0/expressir_core.so +0 -0
  183. data/lib/expressir/benchmark.rb +310 -0
  184. data/lib/expressir/changes/item_change.rb +20 -0
  185. data/lib/expressir/changes/mapping_change.rb +16 -0
  186. data/lib/expressir/changes/schema_change.rb +85 -0
  187. data/lib/expressir/changes/version_change.rb +26 -0
  188. data/lib/expressir/changes.rb +9 -0
  189. data/lib/expressir/cli.rb +148 -0
  190. data/lib/expressir/commands/base.rb +25 -0
  191. data/lib/expressir/commands/benchmark.rb +59 -0
  192. data/lib/expressir/commands/benchmark_cache.rb +80 -0
  193. data/lib/expressir/commands/changes.rb +34 -0
  194. data/lib/expressir/commands/changes_import_eengine.rb +146 -0
  195. data/lib/expressir/commands/changes_validate.rb +63 -0
  196. data/lib/expressir/commands/check.rb +56 -0
  197. data/lib/expressir/commands/clean.rb +20 -0
  198. data/lib/expressir/commands/coverage.rb +458 -0
  199. data/lib/expressir/commands/expand.rb +26 -0
  200. data/lib/expressir/commands/file_violations.rb +70 -0
  201. data/lib/expressir/commands/fix.rb +33 -0
  202. data/lib/expressir/commands/flatten.rb +29 -0
  203. data/lib/expressir/commands/format.rb +43 -0
  204. data/lib/expressir/commands/manifest.rb +420 -0
  205. data/lib/expressir/commands/mapping_validate.rb +68 -0
  206. data/lib/expressir/commands/non_ascii_character.rb +49 -0
  207. data/lib/expressir/commands/non_ascii_violation_collection.rb +301 -0
  208. data/lib/expressir/commands/package.rb +1222 -0
  209. data/lib/expressir/commands/parity_inputs.rb +160 -0
  210. data/lib/expressir/commands/validate.rb +106 -0
  211. data/lib/expressir/commands/validate_ascii.rb +94 -0
  212. data/lib/expressir/commands/validate_load.rb +91 -0
  213. data/lib/expressir/commands/version.rb +9 -0
  214. data/lib/expressir/commands/xsd.rb +23 -0
  215. data/lib/expressir/commands.rb +30 -0
  216. data/lib/expressir/config.rb +60 -0
  217. data/lib/expressir/coverage.rb +510 -0
  218. data/lib/expressir/eengine/arm_compare_report.rb +23 -0
  219. data/lib/expressir/eengine/changes_section.rb +16 -0
  220. data/lib/expressir/eengine/compare_report.rb +69 -0
  221. data/lib/expressir/eengine/mim_compare_report.rb +23 -0
  222. data/lib/expressir/eengine/modified_object.rb +21 -0
  223. data/lib/expressir/eengine.rb +9 -0
  224. data/lib/expressir/errors.rb +113 -0
  225. data/lib/expressir/express/adoc_hyperlink_formatter.rb +30 -0
  226. data/lib/expressir/express/adoc_source_formatter.rb +12 -0
  227. data/lib/expressir/express/ast_key_converter.rb +114 -0
  228. data/lib/expressir/express/builder.rb +277 -0
  229. data/lib/expressir/express/builder_context.rb +22 -0
  230. data/lib/expressir/express/builder_registry.rb +397 -0
  231. data/lib/expressir/express/builders/attribute_decl_builder.rb +32 -0
  232. data/lib/expressir/express/builders/built_in_builder.rb +75 -0
  233. data/lib/expressir/express/builders/constant_builder.rb +108 -0
  234. data/lib/expressir/express/builders/declaration_builder.rb +20 -0
  235. data/lib/expressir/express/builders/derive_clause_builder.rb +14 -0
  236. data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
  237. data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
  238. data/lib/expressir/express/builders/entity_decl_builder.rb +116 -0
  239. data/lib/expressir/express/builders/explicit_attr_builder.rb +49 -0
  240. data/lib/expressir/express/builders/expression_builder.rb +416 -0
  241. data/lib/expressir/express/builders/function_decl_builder.rb +86 -0
  242. data/lib/expressir/express/builders/helpers.rb +148 -0
  243. data/lib/expressir/express/builders/interface_builder.rb +151 -0
  244. data/lib/expressir/express/builders/inverse_attr_builder.rb +43 -0
  245. data/lib/expressir/express/builders/inverse_attr_type_builder.rb +30 -0
  246. data/lib/expressir/express/builders/inverse_clause_builder.rb +14 -0
  247. data/lib/expressir/express/builders/literal_builder.rb +93 -0
  248. data/lib/expressir/express/builders/procedure_decl_builder.rb +82 -0
  249. data/lib/expressir/express/builders/qualifier_builder.rb +102 -0
  250. data/lib/expressir/express/builders/reference_builder.rb +18 -0
  251. data/lib/expressir/express/builders/rule_decl_builder.rb +97 -0
  252. data/lib/expressir/express/builders/schema_body_decl_builder.rb +18 -0
  253. data/lib/expressir/express/builders/schema_decl_builder.rb +56 -0
  254. data/lib/expressir/express/builders/schema_version_builder.rb +34 -0
  255. data/lib/expressir/express/builders/simple_id_builder.rb +17 -0
  256. data/lib/expressir/express/builders/statement_builder.rb +243 -0
  257. data/lib/expressir/express/builders/subtype_constraint_builder.rb +166 -0
  258. data/lib/expressir/express/builders/syntax_builder.rb +30 -0
  259. data/lib/expressir/express/builders/type_builder.rb +238 -0
  260. data/lib/expressir/express/builders/type_decl_builder.rb +26 -0
  261. data/lib/expressir/express/builders/unique_clause_builder.rb +20 -0
  262. data/lib/expressir/express/builders/unique_rule_builder.rb +41 -0
  263. data/lib/expressir/express/builders/where_clause_builder.rb +20 -0
  264. data/lib/expressir/express/builders.rb +55 -0
  265. data/lib/expressir/express/cache.rb +76 -0
  266. data/lib/expressir/express/checker.rb +812 -0
  267. data/lib/expressir/express/concatenator.rb +79 -0
  268. data/lib/expressir/express/core.rb +95 -0
  269. data/lib/expressir/express/error.rb +124 -0
  270. data/lib/expressir/express/formatter.rb +149 -0
  271. data/lib/expressir/express/formatters/data_types_formatter.rb +362 -0
  272. data/lib/expressir/express/formatters/declarations_formatter.rb +753 -0
  273. data/lib/expressir/express/formatters/expressions_formatter.rb +180 -0
  274. data/lib/expressir/express/formatters/literals_formatter.rb +55 -0
  275. data/lib/expressir/express/formatters/references_formatter.rb +53 -0
  276. data/lib/expressir/express/formatters/remark_formatter.rb +270 -0
  277. data/lib/expressir/express/formatters/remark_item_formatter.rb +28 -0
  278. data/lib/expressir/express/formatters/statements_formatter.rb +272 -0
  279. data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +54 -0
  280. data/lib/expressir/express/formatters.rb +22 -0
  281. data/lib/expressir/express/grammar/parser.rb +712 -0
  282. data/lib/expressir/express/grammar.rb +11 -0
  283. data/lib/expressir/express/hyperlink_formatter.rb +35 -0
  284. data/lib/expressir/express/interface_dot.rb +105 -0
  285. data/lib/expressir/express/lazy_repository.rb +211 -0
  286. data/lib/expressir/express/line_map.rb +48 -0
  287. data/lib/expressir/express/listing.rb +174 -0
  288. data/lib/expressir/express/model_traversal.rb +42 -0
  289. data/lib/expressir/express/model_visitor.rb +25 -0
  290. data/lib/expressir/express/node_position_index.rb +342 -0
  291. data/lib/expressir/express/parallel_files.rb +229 -0
  292. data/lib/expressir/express/parser.rb +523 -0
  293. data/lib/expressir/express/pretty_formatter.rb +586 -0
  294. data/lib/expressir/express/pretty_gate.rb +61 -0
  295. data/lib/expressir/express/refs_overlay.rb +47 -0
  296. data/lib/expressir/express/remark_attacher.rb +1098 -0
  297. data/lib/expressir/express/remark_overlay.rb +86 -0
  298. data/lib/expressir/express/remark_scanner.rb +245 -0
  299. data/lib/expressir/express/resolve_references_model_visitor.rb +29 -0
  300. data/lib/expressir/express/schema_block_scanner.rb +137 -0
  301. data/lib/expressir/express/schema_head_formatter.rb +22 -0
  302. data/lib/expressir/express/schema_plain_source_formatter.rb +11 -0
  303. data/lib/expressir/express/schema_source_formatter.rb +15 -0
  304. data/lib/expressir/express/scope_resolver.rb +223 -0
  305. data/lib/expressir/express/self_schema_reference.rb +126 -0
  306. data/lib/expressir/express/shtolo.rb +679 -0
  307. data/lib/expressir/express/smrl_xml.rb +125 -0
  308. data/lib/expressir/express/source_formatter.rb +15 -0
  309. data/lib/expressir/express/streaming_builder.rb +435 -0
  310. data/lib/expressir/express/xsd.rb +259 -0
  311. data/lib/expressir/express.rb +53 -0
  312. data/lib/expressir/liquid.rb +1 -0
  313. data/lib/expressir/manifest/resolver.rb +210 -0
  314. data/lib/expressir/manifest/validator.rb +192 -0
  315. data/lib/expressir/manifest.rb +6 -0
  316. data/lib/expressir/mapping/refpath.rb +857 -0
  317. data/lib/expressir/mapping.rb +253 -0
  318. data/lib/expressir/model/cache.rb +18 -0
  319. data/lib/expressir/model/concerns.rb +42 -0
  320. data/lib/expressir/model/data_types/aggregate.rb +26 -0
  321. data/lib/expressir/model/data_types/array.rb +25 -0
  322. data/lib/expressir/model/data_types/bag.rb +21 -0
  323. data/lib/expressir/model/data_types/binary.rb +19 -0
  324. data/lib/expressir/model/data_types/boolean.rb +15 -0
  325. data/lib/expressir/model/data_types/enumeration.rb +21 -0
  326. data/lib/expressir/model/data_types/enumeration_item.rb +24 -0
  327. data/lib/expressir/model/data_types/generic.rb +24 -0
  328. data/lib/expressir/model/data_types/generic_entity.rb +24 -0
  329. data/lib/expressir/model/data_types/integer.rb +15 -0
  330. data/lib/expressir/model/data_types/list.rb +23 -0
  331. data/lib/expressir/model/data_types/logical.rb +15 -0
  332. data/lib/expressir/model/data_types/number.rb +15 -0
  333. data/lib/expressir/model/data_types/real.rb +17 -0
  334. data/lib/expressir/model/data_types/select.rb +23 -0
  335. data/lib/expressir/model/data_types/set.rb +21 -0
  336. data/lib/expressir/model/data_types/string.rb +19 -0
  337. data/lib/expressir/model/data_types.rb +25 -0
  338. data/lib/expressir/model/declarations/attribute.rb +38 -0
  339. data/lib/expressir/model/declarations/constant.rb +28 -0
  340. data/lib/expressir/model/declarations/derived_attribute.rb +25 -0
  341. data/lib/expressir/model/declarations/entity.rb +62 -0
  342. data/lib/expressir/model/declarations/function.rb +59 -0
  343. data/lib/expressir/model/declarations/informal_proposition_rule.rb +25 -0
  344. data/lib/expressir/model/declarations/interface.rb +37 -0
  345. data/lib/expressir/model/declarations/interface_item.rb +21 -0
  346. data/lib/expressir/model/declarations/interfaced_item.rb +33 -0
  347. data/lib/expressir/model/declarations/inverse_attribute.rb +25 -0
  348. data/lib/expressir/model/declarations/parameter.rb +28 -0
  349. data/lib/expressir/model/declarations/procedure.rb +57 -0
  350. data/lib/expressir/model/declarations/remark_item.rb +21 -0
  351. data/lib/expressir/model/declarations/rule.rb +66 -0
  352. data/lib/expressir/model/declarations/schema.rb +215 -0
  353. data/lib/expressir/model/declarations/schema_version.rb +19 -0
  354. data/lib/expressir/model/declarations/schema_version_item.rb +19 -0
  355. data/lib/expressir/model/declarations/subtype_constraint.rb +32 -0
  356. data/lib/expressir/model/declarations/type.rb +45 -0
  357. data/lib/expressir/model/declarations/unique_rule.rb +26 -0
  358. data/lib/expressir/model/declarations/variable.rb +28 -0
  359. data/lib/expressir/model/declarations/where_rule.rb +26 -0
  360. data/lib/expressir/model/declarations.rb +31 -0
  361. data/lib/expressir/model/dependency_resolver.rb +268 -0
  362. data/lib/expressir/model/exp_file.rb +42 -0
  363. data/lib/expressir/model/expressions/aggregate_initializer.rb +18 -0
  364. data/lib/expressir/model/expressions/aggregate_initializer_item.rb +20 -0
  365. data/lib/expressir/model/expressions/binary_expression.rb +59 -0
  366. data/lib/expressir/model/expressions/entity_constructor.rb +20 -0
  367. data/lib/expressir/model/expressions/function_call.rb +20 -0
  368. data/lib/expressir/model/expressions/interval.rb +29 -0
  369. data/lib/expressir/model/expressions/query_expression.rb +31 -0
  370. data/lib/expressir/model/expressions/unary_expression.rb +25 -0
  371. data/lib/expressir/model/expressions.rb +18 -0
  372. data/lib/expressir/model/identifier.rb +26 -0
  373. data/lib/expressir/model/indexes/entity_index.rb +103 -0
  374. data/lib/expressir/model/indexes/item_graph.rb +185 -0
  375. data/lib/expressir/model/indexes/reference_index.rb +148 -0
  376. data/lib/expressir/model/indexes/type_index.rb +149 -0
  377. data/lib/expressir/model/indexes.rb +12 -0
  378. data/lib/expressir/model/interface_validator.rb +384 -0
  379. data/lib/expressir/model/literals/binary.rb +17 -0
  380. data/lib/expressir/model/literals/integer.rb +17 -0
  381. data/lib/expressir/model/literals/logical.rb +21 -0
  382. data/lib/expressir/model/literals/real.rb +17 -0
  383. data/lib/expressir/model/literals/string.rb +20 -0
  384. data/lib/expressir/model/literals.rb +13 -0
  385. data/lib/expressir/model/model_element.rb +377 -0
  386. data/lib/expressir/model/references/attribute_reference.rb +19 -0
  387. data/lib/expressir/model/references/group_reference.rb +19 -0
  388. data/lib/expressir/model/references/index_reference.rb +23 -0
  389. data/lib/expressir/model/references/simple_reference.rb +21 -0
  390. data/lib/expressir/model/references.rb +12 -0
  391. data/lib/expressir/model/remark_format.rb +17 -0
  392. data/lib/expressir/model/remark_info.rb +92 -0
  393. data/lib/expressir/model/remark_placement.rb +42 -0
  394. data/lib/expressir/model/repository.rb +483 -0
  395. data/lib/expressir/model/repository_validator.rb +293 -0
  396. data/lib/expressir/model/search_engine.rb +551 -0
  397. data/lib/expressir/model/statements/alias.rb +31 -0
  398. data/lib/expressir/model/statements/assignment.rb +23 -0
  399. data/lib/expressir/model/statements/case.rb +42 -0
  400. data/lib/expressir/model/statements/case_action.rb +20 -0
  401. data/lib/expressir/model/statements/compound.rb +21 -0
  402. data/lib/expressir/model/statements/escape.rb +18 -0
  403. data/lib/expressir/model/statements/if.rb +26 -0
  404. data/lib/expressir/model/statements/null.rb +18 -0
  405. data/lib/expressir/model/statements/procedure_call.rb +22 -0
  406. data/lib/expressir/model/statements/repeat.rb +40 -0
  407. data/lib/expressir/model/statements/return.rb +20 -0
  408. data/lib/expressir/model/statements/skip.rb +18 -0
  409. data/lib/expressir/model/statements.rb +20 -0
  410. data/lib/expressir/model/supertype_expressions/binary_supertype_expression.rb +25 -0
  411. data/lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb +17 -0
  412. data/lib/expressir/model/supertype_expressions.rb +12 -0
  413. data/lib/expressir/model.rb +39 -0
  414. data/lib/expressir/package/builder.rb +231 -0
  415. data/lib/expressir/package/metadata.rb +79 -0
  416. data/lib/expressir/package/reader.rb +149 -0
  417. data/lib/expressir/package.rb +8 -0
  418. data/lib/expressir/schema_manifest.rb +159 -0
  419. data/lib/expressir/schema_manifest_entry.rb +15 -0
  420. data/lib/expressir/version.rb +8 -0
  421. data/lib/expressir.rb +94 -0
  422. data/lib/tasks/verify_remarks.rake +16 -0
  423. data/rakelib/native.rake +24 -0
  424. data/rakelib/oracle.rake +52 -0
  425. data/rakelib/verify_remarks.rake +16 -0
  426. metadata +692 -0
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ # Remarks are deterministic given the sources, so the batch path
6
+ # persists them as an overlay next to the compiled-set artifact;
7
+ # warm loads re-apply the overlay instead of re-running the
8
+ # {RemarkAttacher}.
9
+ #
10
+ # Nodes are keyed structurally — attribute path plus array index —
11
+ # because {Model::ModelElement#path} is empty for id-less nodes
12
+ # (statements), and the wire is byte-identical between the cold
13
+ # write and the warm apply, so structural keys match exactly.
14
+ module RemarkOverlay
15
+ CAPTURED = %w[remarks remark_items informal_propositions untagged_remarks header].freeze
16
+
17
+ class << self
18
+ def write(set_path, models)
19
+ overlay = {}
20
+ ModelTraversal.each_model(models) do |node, key|
21
+ entry = {}
22
+ CAPTURED.each do |attr|
23
+ next unless node.respond_to?(attr)
24
+
25
+ value = node.public_send(attr)
26
+ entry[attr] = value if attr == "header" ? value : value&.any?
27
+ end
28
+ overlay[key] = entry if entry.any?
29
+ end
30
+ return if overlay.empty?
31
+
32
+ require "json"
33
+ File.write("#{set_path}.remarks.json", JSON.generate(overlay))
34
+ end
35
+
36
+ # Recursively parent restored nodes and invalidate id-memos so
37
+ # find()/resolve_path_in_scope sees them, exactly as the
38
+ # RemarkAttacher's own bookkeeping does.
39
+ def wire_overlay_value(parent, value)
40
+ case value
41
+ when Array
42
+ value.each { |item| wire_overlay_value(parent, item) }
43
+ when Model::ModelElement
44
+ parent_value = parent.is_a?(Model::ModelElement) ? parent : nil
45
+ value.parent = parent_value if value.respond_to?(:parent=)
46
+ if parent_value.respond_to?(:reset_children_by_id)
47
+ parent_value.reset_children_by_id
48
+ end
49
+ value.class.attributes.each_key do |attr|
50
+ next if Model::ModelElement::SKIP_ATTRIBUTES.include?(attr) || attr == :parent
51
+
52
+ inner = value.public_send(attr)
53
+ next unless inner.is_a?(Model::ModelElement) || inner.is_a?(Array)
54
+
55
+ wire_overlay_value(value, inner)
56
+ end
57
+ end
58
+ end
59
+
60
+ def apply(set_path, models)
61
+ overlay_path = "#{set_path}.remarks.json"
62
+ return unless File.exist?(overlay_path)
63
+
64
+ require "json"
65
+ overlay = JSON.parse(File.read(overlay_path))
66
+ ModelTraversal.each_model(models) do |node, key|
67
+ entry = overlay[key]
68
+ next unless entry
69
+
70
+ CAPTURED.each do |attr|
71
+ setter = :"#{attr}="
72
+ next unless entry[attr] && node.respond_to?(setter)
73
+
74
+ node.public_send(setter, entry[attr])
75
+ # The writer casts JSON hashes into model objects; wire
76
+ # the cast collection (the attacher parents every
77
+ # created node and resets the child-id memo — reference
78
+ # resolution relies on both).
79
+ wire_overlay_value(node, node.public_send(attr))
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,245 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ # Scans EXPRESS source text and extracts all remarks (tail and embedded),
6
+ # correctly tracking embedded-remark nesting so that inline `--` inside
7
+ # a `(* ... *)` documentation block is NOT mistaken for a tail remark.
8
+ #
9
+ # Single responsibility: source string -> Array<Remark>. The scanner has
10
+ # no knowledge of the model; attaching remarks to model elements is the
11
+ # job of {RemarkAttacher}.
12
+ #
13
+ # Reference: ISO 10303-11 §7.1.6.
14
+ # tail_remark = '--' [ remark_tag ] { <any char except newline> } '\n'
15
+ # embedded_remark = '(*' [ remark_tag ]
16
+ # { <any char> | nested embedded_remark } '*)'
17
+ #
18
+ # The scanner is a single-pass state machine with four states:
19
+ # :top — outside any remark/string; look for `--`, `(*`, or `'`.
20
+ # :in_tail — inside a tail remark; look only for the next newline.
21
+ # :in_embedded — inside one or more nested embedded remarks; look
22
+ # for the matching `*)` or a nested `(*`, ignoring `--`.
23
+ # :in_string — inside a simple string literal; look for the closing
24
+ # `'`, treating `''` as an escaped quote (ISO 10303-11
25
+ # §7.1.6.5). `--` and `(*` inside a string are content.
26
+ class RemarkScanner
27
+ # Immutable value object describing a single extracted remark.
28
+ # `position` is the byte offset of the opener (`--` or `(*`).
29
+ # `end_position` is the byte offset one past the closer (the newline
30
+ # byte for tail remarks, the byte after `*)` for embedded remarks).
31
+ # `[position, end_position)` is the full byte range the remark
32
+ # occupied in the original source.
33
+ Remark = Struct.new(:position, :end_position, :line, :text, :tag,
34
+ :format, keyword_init: true) do
35
+ def tail?
36
+ format == Model::RemarkFormat::TAIL
37
+ end
38
+
39
+ def embedded?
40
+ format == Model::RemarkFormat::EMBEDDED
41
+ end
42
+
43
+ def tagged?
44
+ !tag.nil? && !tag.empty?
45
+ end
46
+
47
+ # Byte length of the full remark (opener + content + closer).
48
+ def bytesize
49
+ end_position - position
50
+ end
51
+ end
52
+
53
+ # Lexical markers recognised by EXPRESS.
54
+ TAIL_MARKER = "--"
55
+ EMBEDDED_OPEN = "(*"
56
+ EMBEDDED_CLOSE = "*)"
57
+ STRING_QUOTE = "'"
58
+
59
+ # Byte value of `)` — used to detect the `(*)` overlap pattern where
60
+ # the embedded-remark opener `(*` and closer `*)` share the `*`.
61
+ RPAREN_BYTE = ")".ord
62
+
63
+ # Tag forms (see ISO 10303-11 §7.1.6.3 Remark tag).
64
+ # IP-style informal-proposition tags are recognised only in tail remarks
65
+ # (matching historic behaviour); embedded remarks use the quoted form.
66
+ INFORMAL_PROPOSITION_TAG = /\A(IP\d+):\s*(.*)\z/m
67
+ QUOTED_TAG = /\A"([^"]*)"\s*(.*)\z/m
68
+
69
+ # @param source [String] EXPRESS source text (any encoding).
70
+ def initialize(source)
71
+ @source = source
72
+ @source_bytes = source.b
73
+ @line_map = LineMap.new(@source_bytes)
74
+ end
75
+
76
+ # Returns an Array of {Remark}, in source order (by byte position).
77
+ # @return [Array<Remark>]
78
+ def scan
79
+ run_state_machine
80
+ end
81
+
82
+ alias call scan
83
+
84
+ private
85
+
86
+ # Detects the `(*)` overlap pattern: opener `(*` (positions pos, pos+1)
87
+ # and closer `*)` (positions pos+1, pos+2) share the `*` character.
88
+ # Per strict ISO 10303-11 §7.1.6 grammar the opener and closer are
89
+ # distinct tokens that cannot share characters, so `(*)` is technically
90
+ # invalid; we accept it as a 3-character empty embedded remark for
91
+ # robustness (issue #126).
92
+ def empty_overlap_remark?(pos)
93
+ pos + 2 < @source_bytes.bytesize &&
94
+ @source_bytes.getbyte(pos + 2) == RPAREN_BYTE
95
+ end
96
+
97
+ def run_state_machine
98
+ remarks = []
99
+ src = @source_bytes
100
+ pos = 0
101
+
102
+ state = :top
103
+ embedded_depth = 0
104
+ tail_start = nil # byte position of first content char after "--"
105
+ tail_line = nil
106
+ embedded_start = nil # byte position of first content char after "(*"
107
+ embedded_line = nil
108
+
109
+ while pos < src.bytesize
110
+ case state
111
+ when :in_tail
112
+ nl = src.index("\n", pos)
113
+ if nl
114
+ emit_tail(remarks, tail_start, nl, tail_line)
115
+ pos = nl + 1
116
+ state = :top
117
+ else
118
+ emit_tail(remarks, tail_start, src.bytesize, tail_line)
119
+ return remarks
120
+ end
121
+ when :in_embedded
122
+ closing = src.index(EMBEDDED_CLOSE, pos)
123
+ nesting = src.index(EMBEDDED_OPEN, pos)
124
+ if nesting && (!closing || nesting < closing)
125
+ if empty_overlap_remark?(nesting)
126
+ # `(*)` opens and closes immediately; depth unchanged.
127
+ pos = nesting + 3
128
+ else
129
+ embedded_depth += 1
130
+ pos = nesting + EMBEDDED_OPEN.bytesize
131
+ end
132
+ elsif closing
133
+ embedded_depth -= 1
134
+ pos = closing + EMBEDDED_CLOSE.bytesize
135
+ if embedded_depth.zero?
136
+ emit_embedded(remarks, embedded_start, closing, embedded_line)
137
+ state = :top
138
+ end
139
+ else
140
+ # Unclosed embedded remark — terminate scan gracefully.
141
+ return remarks
142
+ end
143
+ when :in_string
144
+ # ISO 10303-11 §7.1.6.5: `''` inside a string is an escaped quote.
145
+ # Find the next `'`; if followed by another `'`, skip both; else
146
+ # the string closes.
147
+ quote_pos = src.index(STRING_QUOTE, pos)
148
+ if quote_pos.nil?
149
+ # Unclosed string — malformed EXPRESS; terminate scan gracefully.
150
+ return remarks
151
+ end
152
+
153
+ if quote_pos + 1 < src.bytesize && src.getbyte(quote_pos + 1) == STRING_QUOTE.ord
154
+ pos = quote_pos + 2
155
+ else
156
+ pos = quote_pos + 1
157
+ state = :top
158
+ end
159
+ else # :top
160
+ next_embed = src.index(EMBEDDED_OPEN, pos)
161
+ next_tail = src.index(TAIL_MARKER, pos)
162
+ next_quote = src.index(STRING_QUOTE, pos)
163
+ if next_embed.nil? && next_tail.nil? && next_quote.nil?
164
+ return remarks
165
+ elsif next_quote && (next_embed.nil? || next_quote < next_embed) &&
166
+ (next_tail.nil? || next_quote < next_tail)
167
+ # String opener wins — enter :in_string and skip the quote.
168
+ pos = next_quote + STRING_QUOTE.bytesize
169
+ state = :in_string
170
+ elsif next_embed && (next_tail.nil? || next_embed <= next_tail)
171
+ if empty_overlap_remark?(next_embed)
172
+ # Standalone `(*)`: empty embedded remark, opener and closer
173
+ # share the `*`. Emit with empty content and continue.
174
+ emit_embedded(remarks, next_embed + EMBEDDED_OPEN.bytesize,
175
+ next_embed + EMBEDDED_OPEN.bytesize,
176
+ @line_map.line_number(next_embed))
177
+ pos = next_embed + 3
178
+ state = :top
179
+ else
180
+ embedded_start = next_embed + EMBEDDED_OPEN.bytesize
181
+ embedded_line = @line_map.line_number(next_embed)
182
+ embedded_depth = 1
183
+ state = :in_embedded
184
+ pos = next_embed + EMBEDDED_OPEN.bytesize
185
+ end
186
+ else
187
+ tail_start = next_tail + TAIL_MARKER.bytesize
188
+ tail_line = @line_map.line_number(next_tail)
189
+ state = :in_tail
190
+ pos = next_tail + TAIL_MARKER.bytesize
191
+ end
192
+ end
193
+ end
194
+
195
+ remarks
196
+ end
197
+
198
+ def emit_tail(remarks, content_start, content_end, line)
199
+ # Slice content from the original (UTF-8) source so the returned text
200
+ # preserves the source encoding. Byte offsets come from the BINARY copy.
201
+ raw = @source.byteslice(content_start...content_end)
202
+ tag, content = parse_tail(raw.strip)
203
+ remarks << Remark.new(
204
+ position: content_start - TAIL_MARKER.bytesize,
205
+ end_position: content_end,
206
+ line: line,
207
+ text: content,
208
+ tag: tag,
209
+ format: Model::RemarkFormat::TAIL,
210
+ )
211
+ end
212
+
213
+ def emit_embedded(remarks, content_start, content_end, line)
214
+ raw = @source.byteslice(content_start...content_end)
215
+ tag, content = parse_embedded(raw)
216
+ remarks << Remark.new(
217
+ position: content_start - EMBEDDED_OPEN.bytesize,
218
+ end_position: content_end + EMBEDDED_CLOSE.bytesize,
219
+ line: line,
220
+ text: content,
221
+ tag: tag,
222
+ format: Model::RemarkFormat::EMBEDDED,
223
+ )
224
+ end
225
+
226
+ # Tail remarks support both quoted tags ("schema.entity" ...) and the
227
+ # shorthand IP-tag form (IP1: ...). Returns [tag, content]; for untagged
228
+ # remarks tag is nil and content is the stripped text.
229
+ def parse_tail(text)
230
+ match = text.match(INFORMAL_PROPOSITION_TAG) || text.match(QUOTED_TAG)
231
+ match ? match.captures : [nil, text]
232
+ end
233
+
234
+ # Embedded remarks only use the quoted tag form.
235
+ def parse_embedded(content)
236
+ stripped = content.strip
237
+ if (m = stripped.match(QUOTED_TAG))
238
+ [m[1], m[2]]
239
+ else
240
+ [nil, stripped]
241
+ end
242
+ end
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,29 @@
1
+ module Expressir
2
+ module Express
3
+ class ResolveReferencesModelVisitor < ModelVisitor
4
+ def visit(node)
5
+ if node.is_a? Model::References::SimpleReference
6
+ visit_references_simple_reference(node)
7
+ end
8
+
9
+ super
10
+ end
11
+
12
+ private
13
+
14
+ def visit_references_simple_reference(node)
15
+ return if node.parent.is_a? Model::References::AttributeReference
16
+ return unless node.id # Skip if no id to resolve
17
+
18
+ base_item = if node.parent.is_a? Model::Declarations::InterfaceItem
19
+ node.find("#{node.parent.parent.schema.id}.#{node.parent.ref.id}")
20
+ else
21
+ node.find(node.id)
22
+ end
23
+ return unless base_item
24
+
25
+ node.base_path = base_item.path
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ # Splits multi-schema EXPRESS source into individual schema blocks.
6
+ #
7
+ # A hand-rolled state machine that skips comments (`(* ... *)`) and
8
+ # string literals, tracks SCHEMA/END_SCHEMA depth, and returns one
9
+ # block per schema declaration. Retained for the future streaming
10
+ # parse path (see TODO.max-perf/02) that parses each schema
11
+ # independently with a fresh memory arena.
12
+ #
13
+ # Extracted from the outer Parser class (TODO.bugs/09) so block-
14
+ # scanning logic lives in one focused module behind one interface.
15
+ module SchemaBlockScanner
16
+ END_SCHEMA_KEYWORD = "END_SCHEMA"
17
+ SCHEMA_KEYWORD = "SCHEMA"
18
+ WHITESPACE_CHARS = [" ", "\t", "\n", "\r"].freeze
19
+
20
+ module_function
21
+
22
+ # Extract individual schema blocks from EXPRESS source.
23
+ #
24
+ # Uses a state machine to properly handle nested comments and strings.
25
+ #
26
+ # @param source [String] EXPRESS source
27
+ # @return [Array<Hash>] Array of {name:, source:, start_pos:, end_pos:}
28
+ # for each schema block found.
29
+ def extract_schema_blocks(source)
30
+ blocks = []
31
+ pos = 0
32
+ len = source.length
33
+
34
+ while pos < len
35
+ pos = skip_ws_and_comments(source, pos)
36
+ break if pos >= len
37
+
38
+ if source[pos..].start_with?(SCHEMA_KEYWORD)
39
+ result = parse_schema_block(source, pos)
40
+ if result
41
+ blocks << result
42
+ pos = result[:end_pos]
43
+ next
44
+ end
45
+ end
46
+
47
+ pos += 1
48
+ end
49
+
50
+ blocks
51
+ end
52
+
53
+ def parse_schema_block(source, start_pos)
54
+ return nil unless source[start_pos..].start_with?(SCHEMA_KEYWORD)
55
+
56
+ pos = start_pos + SCHEMA_KEYWORD.length
57
+ pos = skip_spaces(source, pos)
58
+
59
+ name_start = pos
60
+ while pos < source.length && (source[pos] =~ /[a-zA-Z0-9_]/ || source[pos] == "_")
61
+ pos += 1
62
+ end
63
+ schema_name = source[name_start...pos]
64
+ return nil if schema_name.empty?
65
+
66
+ depth = 1
67
+ search_pos = pos
68
+ end_pos = nil
69
+
70
+ while search_pos < source.length
71
+ if source[search_pos] == '"'
72
+ search_pos += 1
73
+ while search_pos < source.length && source[search_pos] != '"'
74
+ search_pos += 1
75
+ end
76
+ search_pos += 1
77
+ elsif source[search_pos] == "(" && source[search_pos + 1] == "*"
78
+ search_pos += 2
79
+ while search_pos < source.length && !(source[search_pos] == "*" && source[search_pos + 1] == ")")
80
+ search_pos += 1
81
+ end
82
+ search_pos += 2
83
+ elsif source[search_pos..].start_with?(END_SCHEMA_KEYWORD)
84
+ depth -= 1
85
+ if depth.zero?
86
+ end_pos = search_pos + END_SCHEMA_KEYWORD.length
87
+ pos = end_pos
88
+ pos = skip_spaces(source, pos)
89
+ pos += 1 if source[pos] == ";"
90
+ break
91
+ end
92
+ search_pos += END_SCHEMA_KEYWORD.length
93
+ else
94
+ search_pos += 1
95
+ end
96
+ end
97
+
98
+ return nil unless end_pos
99
+
100
+ {
101
+ name: schema_name,
102
+ source: source[start_pos...end_pos],
103
+ start_pos: start_pos,
104
+ end_pos: pos,
105
+ }
106
+ end
107
+
108
+ def skip_spaces(source, pos)
109
+ while pos < source.length && WHITESPACE_CHARS.include?(source[pos])
110
+ pos += 1
111
+ end
112
+ pos
113
+ end
114
+
115
+ def skip_ws_and_comments(source, pos)
116
+ len = source.length
117
+ while pos < len
118
+ c = source[pos]
119
+ if WHITESPACE_CHARS.include?(c)
120
+ pos += 1
121
+ elsif c == "(" && source[pos + 1] == "*"
122
+ pos += 2
123
+ while pos < len - 1 && !(source[pos] == "*" && source[pos + 1] == ")")
124
+ pos += 1
125
+ end
126
+ pos += 2
127
+ else
128
+ break
129
+ end
130
+ end
131
+ pos
132
+ end
133
+
134
+ private_class_method :parse_schema_block, :skip_spaces, :skip_ws_and_comments
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,22 @@
1
+ module Expressir
2
+ module Express
3
+ # Formatter module - format schema as schema head only
4
+ # @example Include into Formatter subclass
5
+ # formatter = Class.new(Expressir::Express::Formatter) do
6
+ # include Expressir::Express::SchemaHeadFormatter
7
+ # end
8
+ module SchemaHeadFormatter
9
+ # @!visibility private
10
+ def self.included(mod)
11
+ unless mod.superclass <= Expressir::Express::Formatter
12
+ raise Error::FormatterMethodMissingError.new("SchemaHeadFormatter",
13
+ "format_declarations_schema/format_declarations_schema_head")
14
+ end
15
+ end
16
+
17
+ def format_declarations_schema(node)
18
+ format_declarations_schema_head(node)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ # Pre-built Formatter subclass rendering the schema head without
6
+ # hyperlinks — the plain `source` face of Schema (#255).
7
+ class SchemaPlainSourceFormatter < Formatter
8
+ include SchemaHeadFormatter
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Express
5
+ # Pre-built Formatter subclass rendering the schema head with
6
+ # hyperlinks: SchemaHeadFormatter + HyperlinkFormatter. Allocated
7
+ # once at load time rather than per call. It backs
8
+ # Schema#source_hyperlinked; Schema#source uses
9
+ # SchemaPlainSourceFormatter, the unlinked counterpart (#255).
10
+ class SchemaSourceFormatter < Formatter
11
+ include SchemaHeadFormatter
12
+ include HyperlinkFormatter
13
+ end
14
+ end
15
+ end