expressir 2.1.31 → 2.2.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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +3 -2
  3. data/.github/workflows/release.yml +6 -0
  4. data/.rubocop_todo.yml +106 -92
  5. data/Gemfile +1 -1
  6. data/README.adoc +372 -1
  7. data/docs/_guides/formatter/formatter-architecture.adoc +401 -0
  8. data/docs/_guides/ruby-api/parsing-files.adoc +1 -1
  9. data/docs/_pages/parsers.adoc +31 -5
  10. data/docs/lychee.toml +3 -0
  11. data/expressir.gemspec +3 -2
  12. data/lib/expressir/benchmark.rb +6 -6
  13. data/lib/expressir/cli.rb +9 -0
  14. data/lib/expressir/commands/base.rb +2 -9
  15. data/lib/expressir/commands/format.rb +30 -0
  16. data/lib/expressir/commands/package.rb +92 -87
  17. data/lib/expressir/commands/validate_ascii.rb +2 -4
  18. data/lib/expressir/commands/validate_load.rb +8 -5
  19. data/lib/expressir/coverage.rb +15 -11
  20. data/lib/expressir/errors.rb +115 -0
  21. data/lib/expressir/express/builder.rb +350 -0
  22. data/lib/expressir/express/builders/attribute_decl_builder.rb +38 -0
  23. data/lib/expressir/express/builders/built_in_builder.rb +88 -0
  24. data/lib/expressir/express/builders/constant_builder.rb +115 -0
  25. data/lib/expressir/express/builders/declaration_builder.rb +24 -0
  26. data/lib/expressir/express/builders/derive_clause_builder.rb +16 -0
  27. data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
  28. data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
  29. data/lib/expressir/express/builders/entity_decl_builder.rb +108 -0
  30. data/lib/expressir/express/builders/explicit_attr_builder.rb +52 -0
  31. data/lib/expressir/express/builders/expression_builder.rb +453 -0
  32. data/lib/expressir/express/builders/function_decl_builder.rb +84 -0
  33. data/lib/expressir/express/builders/helpers.rb +148 -0
  34. data/lib/expressir/express/builders/interface_builder.rb +171 -0
  35. data/lib/expressir/express/builders/inverse_attr_builder.rb +45 -0
  36. data/lib/expressir/express/builders/inverse_attr_type_builder.rb +36 -0
  37. data/lib/expressir/express/builders/inverse_clause_builder.rb +16 -0
  38. data/lib/expressir/express/builders/literal_builder.rb +107 -0
  39. data/lib/expressir/express/builders/procedure_decl_builder.rb +80 -0
  40. data/lib/expressir/express/builders/qualifier_builder.rb +128 -0
  41. data/lib/expressir/express/builders/reference_builder.rb +27 -0
  42. data/lib/expressir/express/builders/rule_decl_builder.rb +95 -0
  43. data/lib/expressir/express/builders/schema_body_decl_builder.rb +22 -0
  44. data/lib/expressir/express/builders/schema_decl_builder.rb +62 -0
  45. data/lib/expressir/express/builders/schema_version_builder.rb +40 -0
  46. data/lib/expressir/express/builders/simple_id_builder.rb +26 -0
  47. data/lib/expressir/express/builders/statement_builder.rb +250 -0
  48. data/lib/expressir/express/builders/subtype_constraint_builder.rb +188 -0
  49. data/lib/expressir/express/builders/syntax_builder.rb +19 -0
  50. data/lib/expressir/express/builders/token_builder.rb +15 -0
  51. data/lib/expressir/express/builders/type_builder.rb +264 -0
  52. data/lib/expressir/express/builders/type_decl_builder.rb +32 -0
  53. data/lib/expressir/express/builders/unique_clause_builder.rb +22 -0
  54. data/lib/expressir/express/builders/unique_rule_builder.rb +36 -0
  55. data/lib/expressir/express/builders/where_clause_builder.rb +22 -0
  56. data/lib/expressir/express/builders.rb +43 -0
  57. data/lib/expressir/express/error.rb +18 -2
  58. data/lib/expressir/express/formatter.rb +18 -1508
  59. data/lib/expressir/express/formatters/data_types_formatter.rb +317 -0
  60. data/lib/expressir/express/formatters/declarations_formatter.rb +689 -0
  61. data/lib/expressir/express/formatters/expressions_formatter.rb +160 -0
  62. data/lib/expressir/express/formatters/literals_formatter.rb +46 -0
  63. data/lib/expressir/express/formatters/references_formatter.rb +42 -0
  64. data/lib/expressir/express/formatters/remark_formatter.rb +296 -0
  65. data/lib/expressir/express/formatters/statements_formatter.rb +224 -0
  66. data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +48 -0
  67. data/lib/expressir/express/parser.rb +129 -14
  68. data/lib/expressir/express/pretty_formatter.rb +624 -0
  69. data/lib/expressir/express/remark_attacher.rb +1155 -0
  70. data/lib/expressir/express/resolve_references_model_visitor.rb +1 -0
  71. data/lib/expressir/express/streaming_builder.rb +467 -0
  72. data/lib/expressir/express/transformer/remark_handling.rb +196 -0
  73. data/lib/expressir/model/identifier.rb +1 -1
  74. data/lib/expressir/model/model_element.rb +30 -2
  75. data/lib/expressir/model/remark_info.rb +51 -0
  76. data/lib/expressir/model/search_engine.rb +58 -9
  77. data/lib/expressir/version.rb +1 -1
  78. data/lib/expressir.rb +6 -4
  79. metadata +71 -7
  80. data/lib/expressir/express/visitor.rb +0 -2815
@@ -13,11 +13,13 @@ module Expressir
13
13
  attribute :_class, :string, default: -> { send(:name) },
14
14
  polymorphic_class: true
15
15
  attribute :source, :string
16
- attribute :untagged_remarks, :string, collection: true
16
+ attribute :source_offset, :integer
17
+ attribute :untagged_remarks, RemarkInfo, collection: true
17
18
 
18
19
  POLYMORPHIC_CLASS_MAP = {
19
20
  "Expressir::Model::Cache" => "Expressir::Model::Cache",
20
21
  "Expressir::Model::Repository" => "Expressir::Model::Repository",
22
+ "Expressir::Model::RemarkInfo" => "Expressir::Model::RemarkInfo",
21
23
  "Expressir::Model::DataTypes::Aggregate" => "Expressir::Model::DataTypes::Aggregate",
22
24
  "Expressir::Model::DataTypes::Array" => "Expressir::Model::DataTypes::Array",
23
25
  "Expressir::Model::DataTypes::Bag" => "Expressir::Model::DataTypes::Bag",
@@ -136,7 +138,7 @@ module Expressir
136
138
  # @param [String] path
137
139
  # @return [ModelElement]
138
140
  def find(path)
139
- return self if path.empty?
141
+ return self if path.nil? || path.empty?
140
142
 
141
143
  path_parts = path.safe_downcase.split(".").map do |current_path|
142
144
  _, _, current_path = current_path.rpartition(":") # ignore prefix
@@ -191,6 +193,32 @@ module Expressir
191
193
  f.format(self)
192
194
  end
193
195
 
196
+ # Add a remark to this element
197
+ # Supports both RemarkInfo objects and legacy strings
198
+ # @param remark_or_info [RemarkInfo, String] Remark to add
199
+ def add_remark(remark_or_info)
200
+ self.untagged_remarks ||= []
201
+
202
+ if remark_or_info.is_a?(RemarkInfo)
203
+ self.untagged_remarks << remark_or_info
204
+ elsif remark_or_info.is_a?(String)
205
+ # Backward compatibility: assume embedded format for strings
206
+ self.untagged_remarks << RemarkInfo.new(text: remark_or_info,
207
+ format: "embedded")
208
+ end
209
+ end
210
+
211
+ # Get all remarks as RemarkInfo objects
212
+ # Converts legacy string remarks to RemarkInfo for consistency
213
+ # @return [Array<RemarkInfo>] Array of RemarkInfo objects
214
+ def remark_infos
215
+ return [] if untagged_remarks.nil?
216
+
217
+ (untagged_remarks || []).map do |r|
218
+ r.is_a?(RemarkInfo) ? r : RemarkInfo.new(text: r, format: "embedded")
219
+ end
220
+ end
221
+
194
222
  private
195
223
 
196
224
  # @return [nil]
@@ -0,0 +1,51 @@
1
+ module Expressir
2
+ module Model
3
+ # Represents a remark with its format and optional tag
4
+ # Supports both tail remarks (-- ...) and embedded remarks ((* ... *))
5
+ # Can include optional tags for associating remarks with specific items
6
+ class RemarkInfo < Lutaml::Model::Serializable
7
+ attribute :text, :string
8
+ attribute :format, :string, default: "embedded" # 'tail' or 'embedded'
9
+ attribute :tag, :string # optional remark tag like "entity.attr"
10
+
11
+ # Check if this is a tail remark
12
+ # @return [Boolean] True if format is 'tail'
13
+ def tail?
14
+ format == "tail"
15
+ end
16
+
17
+ # Check if this is an embedded remark
18
+ # @return [Boolean] True if format is 'embedded'
19
+ def embedded?
20
+ format == "embedded"
21
+ end
22
+
23
+ # Check if this remark has a tag
24
+ # @return [Boolean] True if tag is present
25
+ def tagged?
26
+ !tag.nil? && !tag.empty?
27
+ end
28
+
29
+ # For backward compatibility with string-based remarks
30
+ # @return [String] The remark text
31
+ def to_s
32
+ text.to_s
33
+ end
34
+
35
+ # YAML serialization
36
+ yaml do
37
+ map "text", to: :text
38
+ map "format", to: :format
39
+ map "tag", to: :tag
40
+ end
41
+
42
+ # XML serialization
43
+ xml do
44
+ root "remark_info"
45
+ map_element "text", to: :text
46
+ map_element "format", to: :format
47
+ map_element "tag", to: :tag
48
+ end
49
+ end
50
+ end
51
+ end
@@ -146,10 +146,19 @@ module Expressir
146
146
  # @return [Boolean] True if matches
147
147
  def matches_pattern?(element, pattern_parts, _element_type,
148
148
  case_sensitive: false, regex: false, exact: false)
149
- element_path = element.respond_to?(:path) ? element.path : element.id
149
+ # Duck typing - check if element responds to path/id
150
+ element_path = begin
151
+ element.path
152
+ rescue StandardError
153
+ element.id
154
+ end
150
155
  return false unless element_path
151
156
 
152
- element_id = element.respond_to?(:id) ? element.id : nil
157
+ element_id = begin
158
+ element.id
159
+ rescue StandardError
160
+ nil
161
+ end
153
162
 
154
163
  search_path = case_sensitive ? element_path : element_path.downcase
155
164
  search_id = element_id && !case_sensitive ? element_id.downcase : element_id
@@ -434,16 +443,35 @@ module Expressir
434
443
  # @param type [String] Element type
435
444
  # @return [Hash] Element data
436
445
  def element_to_hash(element, type)
446
+ # Duck typing - try to get id/path from element
447
+ element_id = begin
448
+ element.id
449
+ rescue StandardError
450
+ nil
451
+ end
452
+
453
+ element_path = begin
454
+ element.path
455
+ rescue StandardError
456
+ nil
457
+ end
458
+
437
459
  hash = {
438
- id: element.respond_to?(:id) ? element.id : nil,
460
+ id: element_id,
439
461
  type: type,
440
- path: element.respond_to?(:path) ? element.path : nil,
462
+ path: element_path,
441
463
  }
442
464
 
443
465
  # Add schema for non-schema elements
444
- if type != "schema" && element.respond_to?(:parent)
445
- schema = find_parent_schema(element)
446
- hash[:schema] = schema.id if schema
466
+ if type != "schema"
467
+ begin
468
+ if element.parent
469
+ schema = find_parent_schema(element)
470
+ hash[:schema] = schema.id if schema
471
+ end
472
+ rescue StandardError
473
+ # Element doesn't have parent or parent chain
474
+ end
447
475
  end
448
476
 
449
477
  # Add category for types
@@ -460,9 +488,30 @@ module Expressir
460
488
  def find_parent_schema(element)
461
489
  current = element
462
490
  while current
463
- return current if current.is_a?(Declarations::Schema)
491
+ # Duck typing - check if this looks like a schema
492
+ # A schema has no parent or is explicitly a Schema type
493
+ begin
494
+ # First check using is_a? for real objects
495
+ if current.is_a?(Declarations::Schema)
496
+ return current
497
+ end
498
+
499
+ # For mock objects, check if parent is nil and has id (likely a schema)
500
+ if !current.respond_to?(:parent) || current.parent.nil?
501
+ # This might be a schema - check if it has an id
502
+ if current.respond_to?(:id) && current.id
503
+ return current
504
+ end
505
+ end
506
+ rescue StandardError
507
+ # Ignore errors from type checking
508
+ end
464
509
 
465
- current = current.parent
510
+ current = begin
511
+ current.parent
512
+ rescue StandardError
513
+ nil
514
+ end
466
515
  end
467
516
  nil
468
517
  end
@@ -1,3 +1,3 @@
1
1
  module Expressir
2
- VERSION = "2.1.31".freeze
2
+ VERSION = "2.2.1".freeze
3
3
  end
data/lib/expressir.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require_relative "expressir/version"
2
+ require_relative "expressir/errors"
2
3
  require_relative "expressir/cli"
3
4
  require_relative "expressir/config"
4
5
  require_relative "expressir/benchmark"
@@ -28,9 +29,6 @@ else
28
29
  end
29
30
 
30
31
  module Expressir
31
- class Error < StandardError; end
32
- class InvalidSchemaManifestError < Error; end
33
-
34
32
  def self.root
35
33
  File.dirname(__dir__)
36
34
  end
@@ -41,16 +39,19 @@ module Expressir
41
39
 
42
40
  # Autoload for Express module classes
43
41
  module Express
42
+ autoload :Builder, "expressir/express/builder"
44
43
  autoload :Cache, "expressir/express/cache"
45
44
  autoload :Error, "expressir/express/error"
46
45
  autoload :Formatter, "expressir/express/formatter"
47
46
  autoload :HyperlinkFormatter, "expressir/express/hyperlink_formatter"
48
47
  autoload :ModelVisitor, "expressir/express/model_visitor"
49
48
  autoload :Parser, "expressir/express/parser"
49
+ autoload :PrettyFormatter, "expressir/express/pretty_formatter"
50
+ autoload :RemarkAttacher, "expressir/express/remark_attacher"
50
51
  autoload :ResolveReferencesModelVisitor,
51
52
  "expressir/express/resolve_references_model_visitor"
52
53
  autoload :SchemaHeadFormatter, "expressir/express/schema_head_formatter"
53
- autoload :Visitor, "expressir/express/visitor"
54
+ autoload :StreamingBuilder, "expressir/express/streaming_builder"
54
55
  end
55
56
 
56
57
  # Autoload for Model module classes
@@ -61,6 +62,7 @@ module Expressir
61
62
  autoload :Repository, "expressir/model/repository"
62
63
  autoload :RepositoryValidator, "expressir/model/repository_validator"
63
64
  autoload :DependencyResolver, "expressir/model/dependency_resolver"
65
+ autoload :RemarkInfo, "expressir/model/remark_info"
64
66
 
65
67
  module Indexes
66
68
  autoload :EntityIndex, "expressir/model/indexes/entity_index"
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.1.31
4
+ version: 2.2.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: 2025-12-11 00:00:00.000000000 Z
11
+ date: 2026-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: benchmark
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: benchmark-ips
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -109,19 +123,19 @@ dependencies:
109
123
  - !ruby/object:Gem::Version
110
124
  version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
- name: parslet
126
+ name: parsanol
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - "~>"
116
130
  - !ruby/object:Gem::Version
117
- version: '2.0'
131
+ version: '1.1'
118
132
  type: :runtime
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
135
  requirements:
122
136
  - - "~>"
123
137
  - !ruby/object:Gem::Version
124
- version: '2.0'
138
+ version: '1.1'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: ruby-progressbar
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -219,6 +233,7 @@ files:
219
233
  - docs/_guides/cli/managing-changes.adoc
220
234
  - docs/_guides/cli/validate-ascii.adoc
221
235
  - docs/_guides/cli/validate-schemas.adoc
236
+ - docs/_guides/formatter/formatter-architecture.adoc
222
237
  - docs/_guides/index.adoc
223
238
  - docs/_guides/ler/creating-packages.adoc
224
239
  - docs/_guides/ler/index.adoc
@@ -304,16 +319,64 @@ files:
304
319
  - lib/expressir/eengine/compare_report.rb
305
320
  - lib/expressir/eengine/mim_compare_report.rb
306
321
  - lib/expressir/eengine/modified_object.rb
322
+ - lib/expressir/errors.rb
323
+ - lib/expressir/express/builder.rb
324
+ - lib/expressir/express/builders.rb
325
+ - lib/expressir/express/builders/attribute_decl_builder.rb
326
+ - lib/expressir/express/builders/built_in_builder.rb
327
+ - lib/expressir/express/builders/constant_builder.rb
328
+ - lib/expressir/express/builders/declaration_builder.rb
329
+ - lib/expressir/express/builders/derive_clause_builder.rb
330
+ - lib/expressir/express/builders/derived_attr_builder.rb
331
+ - lib/expressir/express/builders/domain_rule_builder.rb
332
+ - lib/expressir/express/builders/entity_decl_builder.rb
333
+ - lib/expressir/express/builders/explicit_attr_builder.rb
334
+ - lib/expressir/express/builders/expression_builder.rb
335
+ - lib/expressir/express/builders/function_decl_builder.rb
336
+ - lib/expressir/express/builders/helpers.rb
337
+ - lib/expressir/express/builders/interface_builder.rb
338
+ - lib/expressir/express/builders/inverse_attr_builder.rb
339
+ - lib/expressir/express/builders/inverse_attr_type_builder.rb
340
+ - lib/expressir/express/builders/inverse_clause_builder.rb
341
+ - lib/expressir/express/builders/literal_builder.rb
342
+ - lib/expressir/express/builders/procedure_decl_builder.rb
343
+ - lib/expressir/express/builders/qualifier_builder.rb
344
+ - lib/expressir/express/builders/reference_builder.rb
345
+ - lib/expressir/express/builders/rule_decl_builder.rb
346
+ - lib/expressir/express/builders/schema_body_decl_builder.rb
347
+ - lib/expressir/express/builders/schema_decl_builder.rb
348
+ - lib/expressir/express/builders/schema_version_builder.rb
349
+ - lib/expressir/express/builders/simple_id_builder.rb
350
+ - lib/expressir/express/builders/statement_builder.rb
351
+ - lib/expressir/express/builders/subtype_constraint_builder.rb
352
+ - lib/expressir/express/builders/syntax_builder.rb
353
+ - lib/expressir/express/builders/token_builder.rb
354
+ - lib/expressir/express/builders/type_builder.rb
355
+ - lib/expressir/express/builders/type_decl_builder.rb
356
+ - lib/expressir/express/builders/unique_clause_builder.rb
357
+ - lib/expressir/express/builders/unique_rule_builder.rb
358
+ - lib/expressir/express/builders/where_clause_builder.rb
307
359
  - lib/expressir/express/cache.rb
308
360
  - lib/expressir/express/error.rb
309
361
  - lib/expressir/express/formatter.rb
362
+ - lib/expressir/express/formatters/data_types_formatter.rb
363
+ - lib/expressir/express/formatters/declarations_formatter.rb
364
+ - lib/expressir/express/formatters/expressions_formatter.rb
365
+ - lib/expressir/express/formatters/literals_formatter.rb
366
+ - lib/expressir/express/formatters/references_formatter.rb
367
+ - lib/expressir/express/formatters/remark_formatter.rb
310
368
  - lib/expressir/express/formatters/remark_item_formatter.rb
369
+ - lib/expressir/express/formatters/statements_formatter.rb
370
+ - lib/expressir/express/formatters/supertype_expressions_formatter.rb
311
371
  - lib/expressir/express/hyperlink_formatter.rb
312
372
  - lib/expressir/express/model_visitor.rb
313
373
  - lib/expressir/express/parser.rb
374
+ - lib/expressir/express/pretty_formatter.rb
375
+ - lib/expressir/express/remark_attacher.rb
314
376
  - lib/expressir/express/resolve_references_model_visitor.rb
315
377
  - lib/expressir/express/schema_head_formatter.rb
316
- - lib/expressir/express/visitor.rb
378
+ - lib/expressir/express/streaming_builder.rb
379
+ - lib/expressir/express/transformer/remark_handling.rb
317
380
  - lib/expressir/liquid.rb
318
381
  - lib/expressir/manifest/resolver.rb
319
382
  - lib/expressir/manifest/validator.rb
@@ -382,6 +445,7 @@ files:
382
445
  - lib/expressir/model/references/group_reference.rb
383
446
  - lib/expressir/model/references/index_reference.rb
384
447
  - lib/expressir/model/references/simple_reference.rb
448
+ - lib/expressir/model/remark_info.rb
385
449
  - lib/expressir/model/repository.rb
386
450
  - lib/expressir/model/repository_validator.rb
387
451
  - lib/expressir/model/search_engine.rb
@@ -421,7 +485,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
421
485
  requirements:
422
486
  - - ">="
423
487
  - !ruby/object:Gem::Version
424
- version: 3.0.0
488
+ version: 3.2.0
425
489
  required_rubygems_version: !ruby/object:Gem::Requirement
426
490
  requirements:
427
491
  - - ">="