expressir 2.4.0 → 2.4.1

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 (109) hide show
  1. checksums.yaml +4 -4
  2. data/TODO.bugs/01-stale-transformer-autoload.md +39 -0
  3. data/TODO.bugs/02-parser-class-instance-vars.md +36 -0
  4. data/TODO.bugs/03-builder-mutable-state.md +43 -0
  5. data/TODO.bugs/04-formatter-public-send-dispatch.md +53 -0
  6. data/TODO.bugs/05-anonymous-formatter-subclass.md +45 -0
  7. data/TODO.bugs/06-collection-registry-single-source.md +53 -0
  8. data/TODO.bugs/07-require-relative-cleanup.md +42 -0
  9. data/TODO.bugs/08-require-expressir-in-commands.md +34 -0
  10. data/TODO.bugs/09-parser-split.md +53 -0
  11. data/TODO.bugs/10-to-s-override.md +42 -0
  12. data/TODO.bugs/11-parser-class-variables.md +39 -0
  13. data/TODO.bugs/12-marker-modules-vs-registry.md +64 -0
  14. data/TODO.bugs/13-string-literal-scanner-limitation.md +52 -0
  15. data/TODO.bugs/14-model-formatting-leak.md +30 -0
  16. data/TODO.bugs/15-expression-children-macro.md +27 -0
  17. data/TODO.bugs/16-pretty-formatter-duplication.md +28 -0
  18. data/TODO.bugs/17-snake-case-cache-mutable-constant.md +28 -0
  19. data/TODO.bugs/18-const-get-private-constants.md +30 -0
  20. data/TODO.bugs/19-format-methods-public.md +22 -0
  21. data/TODO.bugs/20-coverage-nested-entities-dedup.md +20 -0
  22. data/TODO.bugs/21-operator-tokens-secondary-dispatch.md +21 -0
  23. data/TODO.bugs/22-builder-fast-path-wrappers.md +32 -0
  24. data/TODO.bugs/23-coverage-inverse-maps.md +21 -0
  25. data/TODO.bugs/24-streaming-builder-complexity.md +19 -0
  26. data/TODO.bugs/25-debug-puts-in-production.md +21 -0
  27. data/TODO.bugs/26-generic-entity-children-misplaced.md +21 -0
  28. data/TODO.bugs/27-package-build-god-method.md +19 -0
  29. data/TODO.bugs/28-package-god-class.md +30 -0
  30. data/TODO.bugs/29-validate-ascii-god-class.md +24 -0
  31. data/TODO.bugs/30-unicode-map-extraction.md +19 -0
  32. data/TODO.bugs/README.md +43 -0
  33. data/docs/_tutorials/formatting-schemas.adoc +89 -0
  34. data/docs/_tutorials/index.adoc +10 -0
  35. data/docs/lychee.toml +3 -0
  36. data/expressir.gemspec +4 -2
  37. data/lib/expressir/commands/changes_import_eengine.rb +0 -6
  38. data/lib/expressir/commands/changes_validate.rb +0 -2
  39. data/lib/expressir/commands/clean.rb +1 -1
  40. data/lib/expressir/commands/file_violations.rb +70 -0
  41. data/lib/expressir/commands/format.rb +1 -1
  42. data/lib/expressir/commands/non_ascii_character.rb +49 -0
  43. data/lib/expressir/commands/non_ascii_violation_collection.rb +301 -0
  44. data/lib/expressir/commands/package.rb +138 -185
  45. data/lib/expressir/commands/validate_ascii.rb +0 -510
  46. data/lib/expressir/commands/version.rb +1 -1
  47. data/lib/expressir/commands.rb +3 -0
  48. data/lib/expressir/coverage.rb +49 -117
  49. data/lib/expressir/express/builder.rb +74 -86
  50. data/lib/expressir/express/builder_context.rb +22 -0
  51. data/lib/expressir/express/builders/expression_builder.rb +16 -16
  52. data/lib/expressir/express/cache.rb +35 -8
  53. data/lib/expressir/express/error.rb +7 -0
  54. data/lib/expressir/express/formatter.rb +33 -18
  55. data/lib/expressir/express/formatters/declarations_formatter.rb +24 -2
  56. data/lib/expressir/express/formatters/remark_formatter.rb +75 -2
  57. data/lib/expressir/express/formatters/statements_formatter.rb +20 -3
  58. data/lib/expressir/express/grammar/parser.rb +705 -0
  59. data/lib/expressir/express/grammar.rb +11 -0
  60. data/lib/expressir/express/node_position_index.rb +215 -0
  61. data/lib/expressir/express/parser.rb +114 -884
  62. data/lib/expressir/express/pretty_formatter.rb +23 -5
  63. data/lib/expressir/express/remark_attacher.rb +475 -577
  64. data/lib/expressir/express/remark_scanner.rb +84 -19
  65. data/lib/expressir/express/schema_block_scanner.rb +136 -0
  66. data/lib/expressir/express/schema_source_formatter.rb +15 -0
  67. data/lib/expressir/express/scope_resolver.rb +194 -0
  68. data/lib/expressir/express/source_formatter.rb +15 -0
  69. data/lib/expressir/express/streaming_builder.rb +147 -176
  70. data/lib/expressir/express.rb +8 -6
  71. data/lib/expressir/model/concerns.rb +3 -0
  72. data/lib/expressir/model/data_types/generic_entity.rb +6 -6
  73. data/lib/expressir/model/declarations/entity.rb +5 -0
  74. data/lib/expressir/model/declarations/function.rb +5 -0
  75. data/lib/expressir/model/declarations/procedure.rb +5 -0
  76. data/lib/expressir/model/declarations/rule.rb +6 -0
  77. data/lib/expressir/model/declarations/schema.rb +21 -8
  78. data/lib/expressir/model/declarations/type.rb +3 -0
  79. data/lib/expressir/model/exp_file.rb +2 -0
  80. data/lib/expressir/model/expressions/aggregate_initializer.rb +1 -0
  81. data/lib/expressir/model/expressions/aggregate_initializer_item.rb +1 -0
  82. data/lib/expressir/model/expressions/binary_expression.rb +1 -0
  83. data/lib/expressir/model/expressions/entity_constructor.rb +1 -0
  84. data/lib/expressir/model/expressions/function_call.rb +1 -0
  85. data/lib/expressir/model/expressions/interval.rb +1 -0
  86. data/lib/expressir/model/expressions/query_expression.rb +2 -0
  87. data/lib/expressir/model/expressions/unary_expression.rb +1 -0
  88. data/lib/expressir/model/model_element.rb +128 -14
  89. data/lib/expressir/model/remark_format.rb +17 -0
  90. data/lib/expressir/model/remark_info.rb +31 -3
  91. data/lib/expressir/model/remark_placement.rb +29 -0
  92. data/lib/expressir/model/statements/alias.rb +2 -0
  93. data/lib/expressir/model/statements/assignment.rb +4 -0
  94. data/lib/expressir/model/statements/case.rb +21 -0
  95. data/lib/expressir/model/statements/case_action.rb +1 -0
  96. data/lib/expressir/model/statements/compound.rb +4 -0
  97. data/lib/expressir/model/statements/escape.rb +3 -0
  98. data/lib/expressir/model/statements/if.rb +5 -0
  99. data/lib/expressir/model/statements/null.rb +3 -0
  100. data/lib/expressir/model/statements/procedure_call.rb +3 -0
  101. data/lib/expressir/model/statements/repeat.rb +3 -0
  102. data/lib/expressir/model/statements/return.rb +3 -0
  103. data/lib/expressir/model/statements/skip.rb +3 -0
  104. data/lib/expressir/model.rb +12 -3
  105. data/lib/expressir/package/builder.rb +2 -2
  106. data/lib/expressir/version.rb +6 -1
  107. data/lib/expressir.rb +38 -3
  108. metadata +63 -5
  109. data/lib/expressir/express/transformer/remark_handling.rb +0 -194
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: expressir
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-07-09 00:00:00.000000000 Z
11
+ date: 2026-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -176,14 +176,14 @@ dependencies:
176
176
  requirements:
177
177
  - - "~>"
178
178
  - !ruby/object:Gem::Version
179
- version: '2.3'
179
+ version: '3.4'
180
180
  type: :runtime
181
181
  prerelease: false
182
182
  version_requirements: !ruby/object:Gem::Requirement
183
183
  requirements:
184
184
  - - "~>"
185
185
  - !ruby/object:Gem::Version
186
- version: '2.3'
186
+ version: '3.4'
187
187
  - !ruby/object:Gem::Dependency
188
188
  name: table_tennis
189
189
  requirement: !ruby/object:Gem::Requirement
@@ -212,6 +212,20 @@ dependencies:
212
212
  - - "~>"
213
213
  - !ruby/object:Gem::Version
214
214
  version: '1.0'
215
+ - !ruby/object:Gem::Dependency
216
+ name: yeptris
217
+ requirement: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - "~>"
220
+ - !ruby/object:Gem::Version
221
+ version: 0.6.1
222
+ type: :runtime
223
+ prerelease: false
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - "~>"
227
+ - !ruby/object:Gem::Version
228
+ version: 0.6.1
215
229
  description: Expressir ("EXPRESS in Ruby") is a Ruby parser for EXPRESS and a set
216
230
  of tools for accessing EXPRESS data models.
217
231
  email:
@@ -237,6 +251,37 @@ files:
237
251
  - Gemfile
238
252
  - README.adoc
239
253
  - Rakefile
254
+ - TODO.bugs/01-stale-transformer-autoload.md
255
+ - TODO.bugs/02-parser-class-instance-vars.md
256
+ - TODO.bugs/03-builder-mutable-state.md
257
+ - TODO.bugs/04-formatter-public-send-dispatch.md
258
+ - TODO.bugs/05-anonymous-formatter-subclass.md
259
+ - TODO.bugs/06-collection-registry-single-source.md
260
+ - TODO.bugs/07-require-relative-cleanup.md
261
+ - TODO.bugs/08-require-expressir-in-commands.md
262
+ - TODO.bugs/09-parser-split.md
263
+ - TODO.bugs/10-to-s-override.md
264
+ - TODO.bugs/11-parser-class-variables.md
265
+ - TODO.bugs/12-marker-modules-vs-registry.md
266
+ - TODO.bugs/13-string-literal-scanner-limitation.md
267
+ - TODO.bugs/14-model-formatting-leak.md
268
+ - TODO.bugs/15-expression-children-macro.md
269
+ - TODO.bugs/16-pretty-formatter-duplication.md
270
+ - TODO.bugs/17-snake-case-cache-mutable-constant.md
271
+ - TODO.bugs/18-const-get-private-constants.md
272
+ - TODO.bugs/19-format-methods-public.md
273
+ - TODO.bugs/20-coverage-nested-entities-dedup.md
274
+ - TODO.bugs/21-operator-tokens-secondary-dispatch.md
275
+ - TODO.bugs/22-builder-fast-path-wrappers.md
276
+ - TODO.bugs/23-coverage-inverse-maps.md
277
+ - TODO.bugs/24-streaming-builder-complexity.md
278
+ - TODO.bugs/25-debug-puts-in-production.md
279
+ - TODO.bugs/26-generic-entity-children-misplaced.md
280
+ - TODO.bugs/27-package-build-god-method.md
281
+ - TODO.bugs/28-package-god-class.md
282
+ - TODO.bugs/29-validate-ascii-god-class.md
283
+ - TODO.bugs/30-unicode-map-extraction.md
284
+ - TODO.bugs/README.md
240
285
  - benchmark/srl_benchmark.rb
241
286
  - benchmark/srl_native_benchmark.rb
242
287
  - benchmark/srl_ruby_benchmark.rb
@@ -291,6 +336,7 @@ files:
291
336
  - docs/_references/index.adoc
292
337
  - docs/_tutorials/creating-ler-package.adoc
293
338
  - docs/_tutorials/documentation-coverage.adoc
339
+ - docs/_tutorials/formatting-schemas.adoc
294
340
  - docs/_tutorials/index.adoc
295
341
  - docs/_tutorials/liquid-templates.adoc
296
342
  - docs/_tutorials/parsing-your-first-schema.adoc
@@ -331,8 +377,11 @@ files:
331
377
  - lib/expressir/commands/changes_validate.rb
332
378
  - lib/expressir/commands/clean.rb
333
379
  - lib/expressir/commands/coverage.rb
380
+ - lib/expressir/commands/file_violations.rb
334
381
  - lib/expressir/commands/format.rb
335
382
  - lib/expressir/commands/manifest.rb
383
+ - lib/expressir/commands/non_ascii_character.rb
384
+ - lib/expressir/commands/non_ascii_violation_collection.rb
336
385
  - lib/expressir/commands/package.rb
337
386
  - lib/expressir/commands/validate.rb
338
387
  - lib/expressir/commands/validate_ascii.rb
@@ -349,6 +398,7 @@ files:
349
398
  - lib/expressir/errors.rb
350
399
  - lib/expressir/express.rb
351
400
  - lib/expressir/express/builder.rb
401
+ - lib/expressir/express/builder_context.rb
352
402
  - lib/expressir/express/builder_registry.rb
353
403
  - lib/expressir/express/builders.rb
354
404
  - lib/expressir/express/builders/attribute_decl_builder.rb
@@ -397,17 +447,23 @@ files:
397
447
  - lib/expressir/express/formatters/remark_item_formatter.rb
398
448
  - lib/expressir/express/formatters/statements_formatter.rb
399
449
  - lib/expressir/express/formatters/supertype_expressions_formatter.rb
450
+ - lib/expressir/express/grammar.rb
451
+ - lib/expressir/express/grammar/parser.rb
400
452
  - lib/expressir/express/hyperlink_formatter.rb
401
453
  - lib/expressir/express/line_map.rb
402
454
  - lib/expressir/express/model_visitor.rb
455
+ - lib/expressir/express/node_position_index.rb
403
456
  - lib/expressir/express/parser.rb
404
457
  - lib/expressir/express/pretty_formatter.rb
405
458
  - lib/expressir/express/remark_attacher.rb
406
459
  - lib/expressir/express/remark_scanner.rb
407
460
  - lib/expressir/express/resolve_references_model_visitor.rb
461
+ - lib/expressir/express/schema_block_scanner.rb
408
462
  - lib/expressir/express/schema_head_formatter.rb
463
+ - lib/expressir/express/schema_source_formatter.rb
464
+ - lib/expressir/express/scope_resolver.rb
465
+ - lib/expressir/express/source_formatter.rb
409
466
  - lib/expressir/express/streaming_builder.rb
410
- - lib/expressir/express/transformer/remark_handling.rb
411
467
  - lib/expressir/liquid.rb
412
468
  - lib/expressir/manifest.rb
413
469
  - lib/expressir/manifest/resolver.rb
@@ -485,7 +541,9 @@ files:
485
541
  - lib/expressir/model/references/group_reference.rb
486
542
  - lib/expressir/model/references/index_reference.rb
487
543
  - lib/expressir/model/references/simple_reference.rb
544
+ - lib/expressir/model/remark_format.rb
488
545
  - lib/expressir/model/remark_info.rb
546
+ - lib/expressir/model/remark_placement.rb
489
547
  - lib/expressir/model/repository.rb
490
548
  - lib/expressir/model/repository_validator.rb
491
549
  - lib/expressir/model/search_engine.rb
@@ -1,194 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "parsanol"
4
-
5
- module Expressir
6
- module Express
7
- # Handles remark extraction and attachment for the Transformer.
8
- # Works with the AST directly, without needing Ctx objects.
9
- module RemarkHandling
10
- extend self
11
-
12
- # Extract all remarks from the AST with their tags and source positions.
13
- # @param ast [Hash] The AST from Parsanol parser
14
- # @param source [String] The original source code
15
- # @return [Array<Hash>] Array of remark info hashes
16
- def extract_remarks(ast, source)
17
- remarks = []
18
-
19
- # Extract embedded remarks (*...*)
20
- extract_embedded_remarks(ast, source, remarks)
21
-
22
- # Extract tail remarks (--...)
23
- extract_tail_remarks(ast, source, remarks)
24
-
25
- remarks
26
- end
27
-
28
- # Attach remarks to model elements based on their tagged paths.
29
- # @param model [Model::ModelElement] The root model element
30
- # @param remarks [Array<Hash>] The extracted remarks
31
- def attach_remarks(model, remarks)
32
- # Group remarks by their tag
33
- tagged_remarks, untagged_remarks = remarks.partition { |r| r[:tag] }
34
-
35
- # Process tagged remarks
36
- tagged_remarks.each do |remark|
37
- target = find_by_path(model, remark[:tag])
38
- if target
39
- add_remark(target, remark[:text])
40
- end
41
- end
42
-
43
- # Process untagged remarks (attach based on position)
44
- attach_untagged_remarks(model, untagged_remarks)
45
- end
46
-
47
- private
48
-
49
- def extract_embedded_remarks(ast, source, remarks, depth = 0)
50
- return if depth > 50 # Prevent infinite recursion
51
-
52
- case ast
53
- when Hash
54
- ast.each do |key, value|
55
- if key == :embeddedRemark
56
- extract_single_embedded_remark(value, source, remarks)
57
- else
58
- extract_embedded_remarks(value, source, remarks, depth + 1)
59
- end
60
- end
61
- when Array
62
- ast.each do |item|
63
- extract_embedded_remarks(item, source, remarks, depth + 1)
64
- end
65
- end
66
- end
67
-
68
- def extract_single_embedded_remark(data, source, remarks)
69
- return unless data
70
-
71
- # Find the slice to get position
72
- slice = find_slice(data)
73
- return unless slice
74
-
75
- # Extract content from the source
76
- content = source[slice.offset...(slice.offset + slice.length)]
77
- return unless content
78
-
79
- # Remove (* and *) delimiters
80
- if content =~ /^\(\*(.*?)\*\)$/m
81
- inner_content = $1.strip
82
- tag, text = parse_tagged_content(inner_content)
83
-
84
- remarks << {
85
- position: slice.offset,
86
- tag: tag,
87
- text: text,
88
- format: :embedded,
89
- }
90
- end
91
- end
92
-
93
- def extract_tail_remarks(ast, source, remarks, depth = 0)
94
- return if depth > 50
95
-
96
- case ast
97
- when Hash
98
- ast.each do |key, value|
99
- if key == :tailRemark
100
- extract_single_tail_remark(value, source, remarks)
101
- else
102
- extract_tail_remarks(value, source, remarks, depth + 1)
103
- end
104
- end
105
- when Array
106
- ast.each do |item|
107
- extract_tail_remarks(item, source, remarks, depth + 1)
108
- end
109
- end
110
- end
111
-
112
- def extract_single_tail_remark(data, source, remarks)
113
- return unless data
114
-
115
- # Find the slice to get position
116
- slice = find_slice(data)
117
- return unless slice
118
-
119
- # Extract content from the source
120
- content = source[slice.offset...(slice.offset + slice.length)]
121
- return unless content
122
-
123
- # Remove -- prefix and any trailing newline
124
- if content =~ /^--\s*(.*?)(?:\n|$)/m
125
- remark_text = $1.strip
126
- tag, text = parse_tagged_content(remark_text)
127
-
128
- remarks << {
129
- position: slice.offset,
130
- tag: tag,
131
- text: text,
132
- format: :tail,
133
- }
134
- end
135
- end
136
-
137
- def find_slice(data, depth = 0)
138
- return nil if depth > 10
139
-
140
- case data
141
- when Hash
142
- data.each_value do |value|
143
- return value if value.is_a?(Parsanol::Slice)
144
-
145
- result = find_slice(value, depth + 1)
146
- return result if result
147
- end
148
- when Array
149
- data.each do |item|
150
- result = find_slice(item, depth + 1)
151
- return result if result
152
- end
153
- end
154
- nil
155
- end
156
-
157
- def parse_tagged_content(content)
158
- if content =~ /^"([^"]+)"\s*(.*)$/m
159
- [$1, $2.strip]
160
- else
161
- [nil, content.strip]
162
- end
163
- end
164
-
165
- def find_by_path(model, path)
166
- return nil unless path
167
- return nil unless model.is_a?(Model::ModelElement)
168
-
169
- # Handle paths with colons (like "wr:WR1" for where rules)
170
- normalized_path = path.gsub(":", ".")
171
-
172
- begin
173
- model.find(normalized_path)
174
- rescue StandardError
175
- nil
176
- end
177
- end
178
-
179
- def add_remark(node, text)
180
- return unless node
181
- return unless node.is_a?(Model::ModelElement)
182
-
183
- node.remarks ||= []
184
- node.remarks << text
185
- end
186
-
187
- def attach_untagged_remarks(model, remarks)
188
- # For untagged remarks, we need to find nearby nodes
189
- # This is more complex and may require source position tracking
190
- # For now, skip untagged remarks as they are less common
191
- end
192
- end
193
- end
194
- end