expressir 2.4.29-arm-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 (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,458 @@
1
+ require "table_tennis"
2
+ require "json"
3
+ require "yaml"
4
+ require "ruby-progressbar"
5
+
6
+ module Expressir
7
+ module Commands
8
+ class Coverage < Base
9
+ def run(paths)
10
+ if paths.empty?
11
+ exit_with_error "No paths specified. Please provide paths to EXPRESS files or directories."
12
+ end
13
+
14
+ reports = collect_reports(paths)
15
+
16
+ if reports.empty?
17
+ exit_with_error "No valid EXPRESS files were processed. Nothing to report."
18
+ end
19
+
20
+ # Generate output based on format
21
+ case options[:format].downcase
22
+ when "json"
23
+ display_json_output(reports)
24
+ when "yaml"
25
+ display_yaml_output(reports)
26
+ else # Default to text
27
+ display_text_output(reports)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def collect_reports(paths)
34
+ reports = []
35
+ ignored_files = parse_ignore_files
36
+
37
+ paths.each do |path|
38
+ handle_path(path, reports, ignored_files)
39
+ end
40
+
41
+ reports
42
+ end
43
+
44
+ def handle_path(path, reports, ignored_files)
45
+ if File.directory?(path)
46
+ handle_directory(path, reports, ignored_files)
47
+ elsif File.extname(path).downcase == ".exp"
48
+ handle_express_file(path, reports, ignored_files)
49
+ elsif [".yml", ".yaml"].include?(File.extname(path).downcase)
50
+ handle_schema_manifest(path, reports, ignored_files)
51
+ else
52
+ say "Unsupported file type: #{path}"
53
+ end
54
+ end
55
+
56
+ def handle_directory(path, reports, ignored_files)
57
+ say "Processing directory: #{path}"
58
+ exp_files = Dir.glob(File.join(path, "**", "*.exp"))
59
+ if exp_files.empty?
60
+ say "No EXPRESS files found in directory: #{path}"
61
+ return
62
+ end
63
+
64
+ say "Found #{exp_files.size} EXPRESS files to process"
65
+
66
+ # Initialize progress bar for directory files
67
+ progress = ProgressBar.create(
68
+ title: "Processing files",
69
+ total: exp_files.size,
70
+ format: "%t: [%B] %p%% %a [%c/%C] %e",
71
+ output: $stdout,
72
+ )
73
+
74
+ # Parse all files and create a repository with progress tracking
75
+ begin
76
+ repository = Expressir::Express::Parser.from_files(
77
+ exp_files, max_processes: options[:max_processes]
78
+ ) do |filename, _schemas, error|
79
+ if error
80
+ say " Error processing #{File.basename(filename)}: #{error.message}"
81
+ end
82
+ progress.increment
83
+ end
84
+ skip_types = parse_skip_types
85
+ report = Expressir::Coverage::Report.from_repository(
86
+ repository,
87
+ skip_types,
88
+ ignored_files,
89
+ )
90
+ reports << report
91
+ rescue StandardError => e
92
+ say "Error processing directory #{path}: #{e.message}"
93
+ end
94
+ end
95
+
96
+ def handle_express_file(path, reports, ignored_files)
97
+ say "Processing file: #{path}"
98
+ begin
99
+ # For a single file, we don't need a progress bar
100
+ skip_types = parse_skip_types
101
+ report = Expressir::Coverage::Report.from_file(path, skip_types,
102
+ ignored_files)
103
+ reports << report
104
+ rescue StandardError => e
105
+ say "Error processing file #{path}: #{e.message}"
106
+ end
107
+ end
108
+
109
+ def handle_schema_manifest(path, reports, ignored_files)
110
+ say "Processing schema manifest: #{path}"
111
+ begin
112
+ # Load schema manifest
113
+ manifest = Expressir::SchemaManifest.from_file(path)
114
+ schema_files = manifest.schemas.map(&:path)
115
+
116
+ say "Found #{schema_files.size} schema files to process"
117
+
118
+ # Initialize progress bar
119
+ if schema_files && !schema_files.empty?
120
+ say "Processing schemas from manifest file"
121
+
122
+ progress = ProgressBar.create(
123
+ title: "Processing schemas",
124
+ total: schema_files.size,
125
+ format: "%t: [%B] %p%% %a [%c/%C] %e",
126
+ output: $stdout,
127
+ )
128
+
129
+ # Process files with progress tracking
130
+ repository = Expressir::Express::Parser.from_files(
131
+ schema_files, max_processes: options[:max_processes]
132
+ ) do |filename, _schemas, error|
133
+ if error
134
+ say " Error processing #{File.basename(filename)}: #{error.message}"
135
+ end
136
+ progress.increment
137
+ end
138
+
139
+ # Create and add the report
140
+ skip_types = parse_skip_types
141
+ report = Expressir::Coverage::Report.from_repository(
142
+ repository,
143
+ skip_types,
144
+ ignored_files,
145
+ )
146
+ reports << report
147
+ end
148
+ rescue StandardError => e
149
+ say "Error processing schema manifest #{path}: #{e.message}"
150
+ end
151
+ end
152
+
153
+ def display_text_output(reports)
154
+ say "\nEXPRESS Documentation Coverage"
155
+ say "=============================="
156
+
157
+ # If multiple reports, display directory coverage first
158
+ if reports.size > 1
159
+ display_directory_coverage(reports)
160
+ end
161
+
162
+ display_file_coverage(reports)
163
+ display_overall_stats(reports)
164
+ end
165
+
166
+ def display_directory_coverage(reports)
167
+ say "\nDirectory Coverage:"
168
+
169
+ # Collect directory data from all reports
170
+ dirs = {}
171
+ reports.each do |report|
172
+ report.directory_reports.each do |dir_report|
173
+ dir = dir_report["directory"]
174
+ dirs[dir] ||= { "total" => 0, "documented" => 0 }
175
+ dirs[dir]["total"] += dir_report["total"]
176
+ dirs[dir]["documented"] += dir_report["documented"]
177
+ end
178
+ end
179
+
180
+ table_data = []
181
+ dirs.each do |dir, stats|
182
+ coverage = stats["total"].positive? ? (stats["documented"].to_f / stats["total"] * 100).round(2) : 100.0
183
+ table_data << {
184
+ directory: dir,
185
+ total: stats["total"].to_s,
186
+ documented: stats["documented"].to_s,
187
+ coverage_percentage: "#{coverage}%",
188
+ }
189
+ end
190
+
191
+ table = TableTennis.new(
192
+ table_data,
193
+ {
194
+ title: "Entity coverage per directory",
195
+ headers: {
196
+ file: "Directory",
197
+ total: "Total Entities",
198
+ documented: "Documented Entities",
199
+ coverage_percentage: "Coverage %",
200
+ },
201
+ titleize: true,
202
+ layout: true,
203
+ },
204
+ )
205
+
206
+ say table
207
+ end
208
+
209
+ def display_file_coverage(reports)
210
+ # Prepare data for table_tennis
211
+ table_data = []
212
+ reports.each do |report|
213
+ report.file_reports.each do |file_report|
214
+ file_path = file_report["file"]
215
+
216
+ # Format undocumented entities as "TYPE name, TYPE name, ..."
217
+ undocumented = file_report["undocumented"].map do |entity_info|
218
+ "#{entity_info['type']} #{entity_info['name']}"
219
+ end.join(", ")
220
+
221
+ coverage = file_report["coverage"].round(2)
222
+
223
+ table_data << {
224
+ filename: File.basename(file_path),
225
+ undocumented_entities: if undocumented.empty?
226
+ "None"
227
+ else
228
+ undocumented
229
+ end,
230
+ coverage_percentage: "#{coverage}%",
231
+ }
232
+ end
233
+ end
234
+
235
+ table = TableTennis.new(
236
+ table_data,
237
+ {
238
+ title: "Entity coverage in file",
239
+ headers: {
240
+ filename: "Filename",
241
+ undocumented_entities: "Undocumented Entities",
242
+ coverage_percentage: "Coverage %",
243
+ },
244
+ titleize: true,
245
+ layout: {
246
+ filename: 30,
247
+ undocumented_entities: 50,
248
+ coverage_percentage: 20,
249
+ },
250
+ },
251
+ )
252
+
253
+ say table
254
+ end
255
+
256
+ def display_overall_stats(reports)
257
+ # Get structured report for overall statistics
258
+ overall = build_structured_report(reports)["overall"]
259
+
260
+ coverage_percentage = overall["coverage_percentage"]
261
+ table_data = [
262
+ {
263
+ metric: "Coverage Percentage",
264
+ value: "#{coverage_percentage}%",
265
+ },
266
+ {
267
+ metric: "Total Entities",
268
+ value: overall["total_entities"].to_s,
269
+ },
270
+ {
271
+ metric: "Documented Entities",
272
+ value: overall["documented_entities"].to_s,
273
+ },
274
+ {
275
+ metric: "Undocumented Entities",
276
+ value: overall["undocumented_entities"].to_s,
277
+ },
278
+ ]
279
+
280
+ table = TableTennis.new(
281
+ table_data,
282
+ {
283
+ title: "Entity overall coverage",
284
+ titleize: true,
285
+ layout: true,
286
+ },
287
+ )
288
+
289
+ say table
290
+ end
291
+
292
+ def build_structured_report(reports)
293
+ # Calculate ignored file statistics
294
+ ignored_files = reports.flat_map(&:ignored_file_reports)
295
+ ignored_entities_count = ignored_files.sum { |f| f["total"] }
296
+
297
+ total = reports.sum { |r| r.total_entities.size }
298
+ documented = reports.sum { |r| r.documented_entities.size }
299
+
300
+ coverage_per = if total.positive?
301
+ (documented.to_f / total * 100).round(2)
302
+ else
303
+ 100.0
304
+ end
305
+
306
+ overall_stats = {
307
+ "total_entities" => reports.sum { |r| r.total_entities.size },
308
+ "documented_entities" => reports.sum do |r|
309
+ r.documented_entities.size
310
+ end,
311
+ "undocumented_entities" => reports.sum do |r|
312
+ r.undocumented_entities.size
313
+ end,
314
+ "coverage_percentage" => coverage_per,
315
+ }
316
+
317
+ # Add ignored file information if there are any
318
+ if ignored_files.any?
319
+ overall_stats["ignored_files_count"] = ignored_files.size
320
+ overall_stats["ignored_entities_count"] = ignored_entities_count
321
+ end
322
+
323
+ structured_report = {
324
+ "overall" => overall_stats,
325
+ "files" => reports.flat_map(&:file_reports),
326
+ "directories" => reports.flat_map(&:directory_reports),
327
+ }
328
+
329
+ # Add ignored files section if there are any
330
+ if ignored_files.any?
331
+ structured_report["ignored_files"] = ignored_files
332
+ end
333
+
334
+ structured_report
335
+ end
336
+
337
+ def display_json_output(reports)
338
+ output_file = options[:output] || "coverage_report.json"
339
+ File.write(output_file,
340
+ JSON.pretty_generate(build_structured_report(reports)))
341
+ say "JSON coverage report written to: #{output_file}"
342
+ end
343
+
344
+ def display_yaml_output(reports)
345
+ output_file = options[:output] || "coverage_report.yaml"
346
+ File.write(output_file, build_structured_report(reports).to_yaml)
347
+ say "YAML coverage report written to: #{output_file}"
348
+ end
349
+
350
+ # Parse and validate the skip_types option
351
+ # @return [Array<String>] Array of validated entity type names
352
+ def parse_skip_types
353
+ skip_types_option = options["exclude"] || options[:exclude]
354
+ return [] unless skip_types_option
355
+
356
+ # Handle both string (comma-separated) and array inputs
357
+ requested_types = if skip_types_option.is_a?(Array)
358
+ skip_types_option.map(&:to_s).map(&:strip).map(&:upcase)
359
+ else
360
+ skip_types_option.split(",").map(&:strip).map(&:upcase)
361
+ end
362
+
363
+ # Validate each type (supports both TYPE and TYPE:SUBTYPE formats)
364
+ requested_types.each do |type|
365
+ validate_skip_type(type)
366
+ end
367
+
368
+ requested_types
369
+ end
370
+
371
+ # Validate a single skip type (supports TYPE:SUBTYPE and FUNCTION:SUBTYPE syntax)
372
+ # @param type [String] The type to validate
373
+ def validate_skip_type(type)
374
+ if type.include?(":")
375
+ # Handle TYPE:SUBTYPE and FUNCTION:SUBTYPE format
376
+ main_type, subtype = type.split(":", 2)
377
+
378
+ # Validate main type
379
+ unless Expressir::Coverage::ENTITY_TYPE_MAP.key?(main_type)
380
+ exit_with_error "Invalid entity type: #{main_type}. " \
381
+ "Valid types are: #{Expressir::Coverage::ENTITY_TYPE_MAP.keys.join(', ')}"
382
+ end
383
+
384
+ # For TYPE, validate subtype
385
+ if main_type == "TYPE"
386
+ unless Expressir::Coverage::TYPE_SUBTYPES.include?(subtype)
387
+ exit_with_error "Invalid TYPE subtype: #{subtype}. " \
388
+ "Valid TYPE subtypes are: #{Expressir::Coverage::TYPE_SUBTYPES.join(', ')}"
389
+ end
390
+ # For FUNCTION, validate subtype
391
+ elsif main_type == "FUNCTION"
392
+ unless subtype == "INNER"
393
+ exit_with_error "Invalid FUNCTION subtype: #{subtype}. " \
394
+ "Valid FUNCTION subtypes are: INNER"
395
+ end
396
+ else
397
+ exit_with_error "Subtype syntax (#{type}) is only supported for TYPE and FUNCTION entities"
398
+ end
399
+ else
400
+ # Handle simple type format
401
+ unless Expressir::Coverage::ENTITY_TYPE_MAP.key?(type)
402
+ exit_with_error "Invalid entity type: #{type}. " \
403
+ "Valid types are: #{Expressir::Coverage::ENTITY_TYPE_MAP.keys.join(', ')}"
404
+ end
405
+ end
406
+ end
407
+
408
+ # Parse and expand ignore files from YAML
409
+ # @return [Hash] Hash mapping absolute file paths to their matched patterns
410
+ def parse_ignore_files
411
+ ignore_files_option = options["ignore_files"] || options[:ignore_files]
412
+ return {} unless ignore_files_option
413
+
414
+ unless File.exist?(ignore_files_option)
415
+ say "Warning: Ignore files YAML not found: #{ignore_files_option}"
416
+ return {}
417
+ end
418
+
419
+ begin
420
+ patterns = YAML.load_file(ignore_files_option)
421
+ unless patterns.is_a?(Array)
422
+ say "Warning: Invalid ignore files YAML format. Expected an array of file patterns."
423
+ return {}
424
+ end
425
+
426
+ ignore_files_dir = File.dirname(File.expand_path(ignore_files_option))
427
+ expanded_files = {}
428
+
429
+ patterns.each do |pattern|
430
+ # Resolve pattern relative to the YAML file's directory
431
+ full_pattern = File.expand_path(pattern, ignore_files_dir)
432
+
433
+ # Expand glob pattern
434
+ matched_files = Dir.glob(full_pattern)
435
+
436
+ if matched_files.empty?
437
+ say "Warning: No files matched pattern: #{pattern}"
438
+ else
439
+ matched_files.each do |file_path|
440
+ # Store absolute path and the original pattern that matched it
441
+ expanded_files[File.expand_path(file_path)] = pattern
442
+ end
443
+ end
444
+ end
445
+
446
+ if expanded_files.any?
447
+ say "Found #{expanded_files.size} files to ignore from patterns"
448
+ end
449
+
450
+ expanded_files
451
+ rescue StandardError => e
452
+ say "Warning: Error processing ignore files YAML #{ignore_files_option}: #{e.message}"
453
+ {}
454
+ end
455
+ end
456
+ end
457
+ end
458
+ end
@@ -0,0 +1,26 @@
1
+ module Expressir
2
+ module Commands
3
+ # `expand` — flattens an interface closure into a single concatenated
4
+ # .exp artifact (expressir#247). Equivalent to eeng's
5
+ # `--concat_schema` over the root schema's closure.
6
+ class Expand < Base
7
+ def run(path)
8
+ root, repository = ParityInputs.root_schema(
9
+ path, manifest: options[:manifest], stepmod: options[:stepmod]
10
+ )
11
+ exit_with_error "schema for #{path} not found in closure" unless root
12
+
13
+ closure = Expressir::Express::Concatenator.closure(root, repository)
14
+
15
+ if options[:output]
16
+ File.open(options[:output], "w") do |io|
17
+ Expressir::Express::Concatenator.write(io, closure)
18
+ end
19
+ say "Concatenated schema written to #{options[:output]}"
20
+ else
21
+ Expressir::Express::Concatenator.write($stdout, closure)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expressir
4
+ module Commands
5
+ class FileViolations
6
+ attr_reader :path, :filename, :directory, :violations
7
+
8
+ def initialize(file_path)
9
+ @path = file_path
10
+ @filename = File.basename(file_path)
11
+ @directory = File.dirname(file_path)
12
+ @characters = {} # Map of characters to NonAsciiCharacter objects
13
+ @violations = [] # List of violations (line, column, etc.)
14
+ end
15
+
16
+ def add_violation(line_number, column, match, char_details, line)
17
+ violation = {
18
+ line_number: line_number,
19
+ column: column,
20
+ match: match,
21
+ char_details: char_details,
22
+ line: line,
23
+ }
24
+
25
+ @violations << violation
26
+
27
+ # Register each character
28
+ char_details.each do |detail|
29
+ char = detail[:char]
30
+ unless @characters[char]
31
+ @characters[char] = NonAsciiCharacter.new(
32
+ char,
33
+ detail[:hex],
34
+ detail[:utf8],
35
+ detail[:is_math],
36
+ detail[:replacement],
37
+ detail[:replacement_type],
38
+ )
39
+ end
40
+
41
+ @characters[char].add_occurrence(line_number, column, line)
42
+ end
43
+ end
44
+
45
+ def violation_count
46
+ @violations.size
47
+ end
48
+
49
+ def unique_characters
50
+ @characters.values
51
+ end
52
+
53
+ def display_path
54
+ "#{File.basename(@directory)}/#{@filename}"
55
+ end
56
+
57
+ def full_path
58
+ File.expand_path(@path)
59
+ end
60
+
61
+ def to_h
62
+ {
63
+ file: display_path,
64
+ count: violation_count,
65
+ non_ascii_characters: unique_characters.map(&:to_h),
66
+ }
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,33 @@
1
+ module Expressir
2
+ module Commands
3
+ # `fix` — rewrites self-schema-qualified references (#125): string
4
+ # literals like `'THIS_SCHEMA.ITEM'` lose the current-schema prefix
5
+ # when the item is local, or gain the item's true defining schema
6
+ # otherwise. Outputs the corrected EXPRESS file.
7
+ class Fix < Base
8
+ def run(path)
9
+ # Load the interface closure (same-dir by default, or --manifest /
10
+ # --stepmod) so SelfSchemaReference can resolve where each item
11
+ # truly comes from.
12
+ files = ParityInputs.closure_paths(
13
+ path, manifest: options[:manifest], stepmod: options[:stepmod]
14
+ ).select { |f| File.exist?(f) }
15
+ repository = Expressir::Express::Parser.from_files(
16
+ files, skip_references: true
17
+ )
18
+ total = repository.schemas.sum do |schema|
19
+ Expressir::Express::SelfSchemaReference.fix!(schema)
20
+ end
21
+
22
+ text = Expressir::Express::Formatter.format(repository)
23
+ if options[:output]
24
+ File.write(options[:output], text)
25
+ say "#{total} self-schema reference(s) fixed; written to " \
26
+ "#{options[:output]}"
27
+ else
28
+ $stdout.write(text)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ module Expressir
2
+ module Commands
3
+ # `flatten` — converts a STEPmod-style multi-schema root into a single
4
+ # ISO 10303-11:1994 longform schema (SHTOLO, expressir#32).
5
+ # Equivalent to eeng's `--flat -mode _longform`.
6
+ class Flatten < Base
7
+ def run(path)
8
+ root, repository = ParityInputs.root_schema(
9
+ path, manifest: options[:manifest], stepmod: options[:stepmod]
10
+ )
11
+ exit_with_error "schema for #{path} not found in closure" unless root
12
+
13
+ longform_name = options[:longform_name] || "#{root.id}_lf"
14
+ extenders = options[:extenders] == "none" ? :none : :all
15
+ flat = Expressir::Express::Shtolo.new(root, repository,
16
+ longform_name: longform_name,
17
+ extenders: extenders).flatten.schema
18
+ text = Expressir::Express::Formatter.format(flat)
19
+
20
+ if options[:output]
21
+ File.write(options[:output], text)
22
+ say "Longform schema written to #{options[:output]}"
23
+ else
24
+ $stdout.write(text)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ module Expressir
2
+ module Commands
3
+ class Format < Base
4
+ def run(path)
5
+ repository = Expressir::Express::Parser.from_file(path)
6
+
7
+ profile = options[:profile] || "iso"
8
+
9
+ case profile.downcase
10
+ when "elf"
11
+ format_with_elf_profile(repository)
12
+ when "iso"
13
+ format_with_iso_profile(repository)
14
+ else
15
+ raise Expressir::InvalidOptionError.new(
16
+ "profile",
17
+ profile,
18
+ valid_options: ["iso", "elf"],
19
+ )
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def format_with_elf_profile(repository)
26
+ formatter_options = {
27
+ indent: options[:indent] || 4,
28
+ provenance: options.fetch(:provenance, true),
29
+ }
30
+
31
+ formatter = Expressir::Express::PrettyFormatter.new(formatter_options)
32
+ say formatter.format(repository)
33
+ end
34
+
35
+ def format_with_iso_profile(repository)
36
+ repository.schemas.each do |schema|
37
+ say "\n(* Expressir formatted schema: #{schema.id} *)\n"
38
+ say schema.format(no_remarks: true)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end