expressir 2.1.19 → 2.1.21

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b68644d000b4b7d47a7e132922afa9b4e9f1d3fb19ba6c3b9e2a8db28c5fd33
4
- data.tar.gz: 132ecfd9ca85168335536626fea46c3648757ccd973823242b04b0744869376c
3
+ metadata.gz: 5523a9cdb1e5b8168a0d2d7262cdd8a5e849b066a3eeaaad90a3bcb3a640fe38
4
+ data.tar.gz: 293acbebeecc50a22ba8bc56aa8413f7e156dac17fa4fa872380aff5a9bf320c
5
5
  SHA512:
6
- metadata.gz: 895f018faf2bbdd075991d45fa22061459b918f907e568e4481a98dd2e0eb96a312cb98d96e2e7de381c7c85841d05631119f7c26e1773ac634377cdac8e6fe2
7
- data.tar.gz: 025421a41b6463548b8ac099fe8b5bc94eb21ee58339f77a6ff028c59ebdb1ac27c5f24ea46050d1fa5b84ee5e80802efcb45b0a549bc733ea833f43c48e0e14
6
+ metadata.gz: b756fab7be254dc71ab78ce9ffdb220c727cc1ef8599c2e293ee2edb35d8fb7f2ab9e127683e7621d5a0ac2df4379efa5ff1c2aeaa8dd7623b94b18d5e778d7e
7
+ data.tar.gz: cb767afb4bef0a7555b9519a29b1cefa14ba3c96278d5154e2c2b5af29e813ba0824ffb7efbfd2e601f2e606f0a5800595b8a97b7998a83dd80c4d99448e7546
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2025-06-04 17:31:42 UTC using RuboCop version 1.75.2.
3
+ # on 2025-06-07 05:08:55 UTC using RuboCop version 1.75.2.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -21,11 +21,31 @@ Layout/LineLength:
21
21
  Exclude:
22
22
  - 'lib/expressir/express/parser.rb'
23
23
 
24
+ # Offense count: 1
25
+ # Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
26
+ Lint/DuplicateBranch:
27
+ Exclude:
28
+ - 'lib/expressir/coverage.rb'
29
+
30
+ # Offense count: 1
31
+ # This cop supports safe autocorrection (--autocorrect).
32
+ Lint/ScriptPermission:
33
+ Exclude:
34
+ - 'update_yaml_fixtures.rb'
35
+
24
36
  # Offense count: 3
25
37
  Lint/ShadowingOuterLocalVariable:
26
38
  Exclude:
27
39
  - 'lib/expressir/express/visitor.rb'
28
40
 
41
+ # Offense count: 2
42
+ # This cop supports safe autocorrection (--autocorrect).
43
+ # Configuration parameters: AutoCorrect, IgnoreEmptyBlocks, AllowUnusedKeywordArguments.
44
+ Lint/UnusedBlockArgument:
45
+ Exclude:
46
+ - 'lib/expressir/express/visitor.rb'
47
+ - 'spec/support/yaml_matchers.rb'
48
+
29
49
  # Offense count: 2
30
50
  # This cop supports safe autocorrection (--autocorrect).
31
51
  # Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
@@ -35,7 +55,7 @@ Lint/UnusedMethodArgument:
35
55
  - 'lib/expressir/express/cache.rb'
36
56
  - 'lib/expressir/express/parser.rb'
37
57
 
38
- # Offense count: 71
58
+ # Offense count: 76
39
59
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
40
60
  Metrics/AbcSize:
41
61
  Exclude:
@@ -54,13 +74,13 @@ Metrics/AbcSize:
54
74
  - 'lib/expressir/model/declarations/schema.rb'
55
75
  - 'lib/expressir/model/model_element.rb'
56
76
 
57
- # Offense count: 1
77
+ # Offense count: 2
58
78
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
59
79
  # AllowedMethods: refine
60
80
  Metrics/BlockLength:
61
81
  Max: 143
62
82
 
63
- # Offense count: 51
83
+ # Offense count: 56
64
84
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
65
85
  Metrics/CyclomaticComplexity:
66
86
  Exclude:
@@ -75,12 +95,12 @@ Metrics/CyclomaticComplexity:
75
95
  - 'lib/expressir/model/model_element.rb'
76
96
  - 'spec/support/model_element_helper.rb'
77
97
 
78
- # Offense count: 94
98
+ # Offense count: 100
79
99
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
80
100
  Metrics/MethodLength:
81
- Max: 50
101
+ Max: 82
82
102
 
83
- # Offense count: 39
103
+ # Offense count: 44
84
104
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
85
105
  Metrics/PerceivedComplexity:
86
106
  Exclude:
@@ -92,6 +112,17 @@ Metrics/PerceivedComplexity:
92
112
  - 'lib/expressir/model/declarations/schema.rb'
93
113
  - 'lib/expressir/model/model_element.rb'
94
114
 
115
+ # Offense count: 1
116
+ # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs.
117
+ # NamePrefix: is_, has_, have_, does_
118
+ # ForbiddenPrefixes: is_, has_, have_, does_
119
+ # AllowedMethods: is_a?
120
+ # MethodDefinitionMacros: define_method, define_singleton_method
121
+ Naming/PredicateName:
122
+ Exclude:
123
+ - 'spec/**/*'
124
+ - 'lib/expressir/coverage.rb'
125
+
95
126
  # Offense count: 5
96
127
  Performance/FixedSize:
97
128
  Exclude:
@@ -101,3 +132,9 @@ Performance/FixedSize:
101
132
  Style/MissingRespondToMissing:
102
133
  Exclude:
103
134
  - 'lib/expressir/express/visitor.rb'
135
+
136
+ # Offense count: 2
137
+ # This cop supports unsafe autocorrection (--autocorrect-all).
138
+ Style/SlicingWithRange:
139
+ Exclude:
140
+ - 'lib/expressir/express/visitor.rb'
data/README.adoc CHANGED
@@ -286,25 +286,190 @@ such as TYPE entities whose descriptions are generated by template strings.
286
286
  # Exclude TYPE entities from coverage analysis
287
287
  expressir coverage --exclude=TYPE schemas/resources/action_schema/action_schema.exp
288
288
 
289
+ # Exclude only SELECT type definitions (useful since TYPE descriptions are often template-generated)
290
+ expressir coverage --exclude=TYPE:SELECT schemas/resources/action_schema/action_schema.exp
291
+
289
292
  # Exclude multiple entity types
290
293
  expressir coverage --exclude=TYPE,CONSTANT,FUNCTION schemas/resources/action_schema/action_schema.exp
291
294
 
295
+ # Exclude parameters and variables (often don't require individual documentation)
296
+ expressir coverage --exclude=PARAMETER,VARIABLE schemas/resources/action_schema/action_schema.exp
297
+
292
298
  # Combine with output format options
293
- expressir coverage --exclude=TYPE --format=json schemas/resources/action_schema/action_schema.exp
299
+ expressir coverage --exclude=TYPE:SELECT --format=json schemas/resources/action_schema/action_schema.exp
300
+ ----
301
+
302
+ ==== Elements checked in documentation coverage
303
+
304
+ Expressir checks documentation coverage for all EXPRESS elements (ModelElement
305
+ subclasses), including:
306
+
307
+ Schema-level entities:
308
+
309
+ `TYPE`:: Type definitions (supports subtype exclusion, see below)
310
+ `ENTITY`:: Entity definitions
311
+ `CONSTANT`:: Constant definitions
312
+ `FUNCTION`:: Function definitions
313
+ `RULE`:: Rule definitions
314
+ `PROCEDURE`:: Procedure definitions
315
+ `SUBTYPE_CONSTRAINT`:: Subtype constraint definitions
316
+ `INTERFACE`:: Interface definitions
317
+
318
+ Nested entities within other constructs:
319
+
320
+ `PARAMETER`:: Function and procedure parameters
321
+ `VARIABLE`:: Variables within functions, rules, and procedures
322
+ `ATTRIBUTE`:: Entity attributes
323
+ `DERIVED_ATTRIBUTE`:: Derived attributes in entities
324
+ `INVERSE_ATTRIBUTE`:: Inverse attributes in entities
325
+ `UNIQUE_RULE`:: Unique rules within entities
326
+ `WHERE_RULE`:: Where rules within entities and types
327
+ `ENUMERATION_ITEM`:: Items within enumeration types
328
+ `INTERFACE_ITEM`:: Items within interfaces
329
+ `INTERFACED_ITEM`:: Interfaced items
330
+ `SCHEMA_VERSION`:: Schema version information
331
+ `SCHEMA_VERSION_ITEM`:: Schema version items
332
+
333
+ ==== TYPE subtype exclusion
334
+
335
+ For TYPE elements, you can exclude specific subtypes using the `TYPE:SUBTYPE`
336
+ syntax:
337
+
338
+ [source, sh]
339
+ ----
340
+ # Exclude only SELECT types
341
+ expressir coverage --exclude=TYPE:SELECT schemas/resources/action_schema/action_schema.exp
342
+
343
+ # Exclude multiple TYPE subtypes
344
+ expressir coverage --exclude=TYPE:SELECT,TYPE:ENUMERATION schemas/resources/action_schema/action_schema.exp
345
+ ----
346
+
347
+ ==== FUNCTION subtype exclusion
348
+
349
+ For FUNCTION elements, you can exclude inner functions (functions nested within
350
+ other functions, rules, or procedures) using the `FUNCTION:INNER` syntax:
351
+
352
+ [source, sh]
353
+ ----
354
+ # Exclude inner functions from coverage analysis
355
+ expressir coverage --exclude=FUNCTION:INNER schemas/resources/action_schema/action_schema.exp
356
+
357
+ # Combine with other exclusions
358
+ expressir coverage --exclude=TYPE:SELECT,FUNCTION:INNER schemas/resources/action_schema/action_schema.exp
359
+ ----
360
+
361
+ This is useful when you want to focus documentation coverage on top-level
362
+ functions while excluding nested helper functions that may not require
363
+ individual documentation.
364
+
365
+ Valid FUNCTION subtypes that can be excluded:
366
+
367
+ `INNER`:: Inner functions nested within other functions, rules, or procedures
368
+ +
369
+ [example]
370
+ ====
371
+ ----
372
+ FUNCTION outer_function : BOOLEAN;
373
+ -- This inner function would be excluded with FUNCTION:INNER
374
+ FUNCTION inner_helper_function : BOOLEAN;
375
+ RETURN (TRUE);
376
+ END_FUNCTION;
377
+
378
+ RETURN (TRUE);
379
+ END_FUNCTION;
380
+ ----
381
+ ====
382
+
383
+ Valid TYPE subtypes that can be excluded:
384
+
385
+ `AGGREGATE`:: Aggregate type
386
+ `ARRAY`:: Array type
387
+ `BAG`:: Bag type
388
+ `BINARY`:: Binary type
389
+ `BOOLEAN`:: Boolean type
390
+ `ENUMERATION`:: Enumeration type
391
+ +
392
+ [example]
393
+ ====
394
+ ----
395
+ TYPE uuid_relationship_role = ENUMERATION OF
396
+ (supersedes,
397
+ merge,
398
+ split,
399
+ derive_from,
400
+ same_as,
401
+ similar_to);
402
+ END_TYPE;
403
+ ----
404
+ ====
405
+
406
+ `GENERIC`:: Generic type
407
+ `GENERIC_ENTITY`:: Generic entity type
408
+ +
409
+ [example]
410
+ ====
411
+ ----
412
+ TYPE uuid_attribute_select = EXTENSIBLE GENERIC_ENTITY SELECT;
413
+ END_TYPE;
414
+ ----
415
+ ====
416
+
417
+ `INTEGER`:: Integer type
418
+ `LIST`:: List type
419
+ +
420
+ [example]
421
+ ====
422
+ ----
423
+ TYPE uuid_list_item = LIST [1:?] OF UNIQUE LIST [1:?] OF UNIQUE uuid_attribute_select;
424
+ END_TYPE;
425
+ ----
426
+ ====
427
+
428
+ `LOGICAL`:: Logical type
429
+ `NUMBER`:: Number type
430
+ `REAL`:: Real type
431
+ `SELECT`:: Select type
432
+ +
433
+ [example]
434
+ ====
435
+ ----
436
+ TYPE uuid_set_or_list_attribute_select = SELECT
437
+ (uuid_list_item,
438
+ uuid_set_item);
439
+ END_TYPE;
440
+ ----
441
+ ====
442
+
443
+ `SET`:: Set type
444
+ +
445
+ [example]
446
+ ====
294
447
  ----
448
+ TYPE uuid_set_item = SET [1:?] OF uuid_attribute_select;
449
+ END_TYPE;
450
+ ----
451
+ ====
452
+
453
+ `STRING`::
454
+ String type
455
+ +
456
+ [example]
457
+ ====
458
+ ----
459
+ TYPE uuid = STRING (36) FIXED;
460
+ END_TYPE;
461
+ ----
462
+ ====
295
463
 
296
- Valid entity types that can be excluded:
464
+ This is particularly useful since TYPE entities with certain subtypes (like
465
+ SELECT) often have descriptions generated by template strings and may not
466
+ require individual remark item coverage.
297
467
 
298
- * `TYPE` - Type definitions
299
- * `ENTITY` - Entity definitions
300
- * `CONSTANT` - Constant definitions
301
- * `FUNCTION` - Function definitions
302
- * `RULE` - Rule definitions
303
- * `PROCEDURE` - Procedure definitions
304
- * `SUBTYPE_CONSTRAINT` - Subtype constraint definitions
468
+ NOTE: ISO 10303 excludes documentation coverage for TYPE:SELECT and
469
+ TYPE:ENUMERATION.
305
470
 
306
- If you specify an invalid entity type, the command will display an error message
307
- with the list of valid types.
471
+ If you specify an invalid entity type or subtype, the command will display an
472
+ error message with the list of valid options.
308
473
 
309
474
  .Example with JSON output:
310
475
  [example]
data/expressir.gemspec CHANGED
@@ -42,5 +42,4 @@ Gem::Specification.new do |spec|
42
42
  spec.add_dependency "ruby-progressbar", "~> 1.11"
43
43
  spec.add_dependency "terminal-table", "~> 3.0"
44
44
  spec.add_dependency "thor", "~> 1.0"
45
- spec.add_dependency "zeitwerk", "~> 2.6"
46
45
  end
data/lib/expressir/cli.rb CHANGED
@@ -55,7 +55,8 @@ module Expressir
55
55
 
56
56
  desc "coverage *PATH", "List EXPRESS entities and check documentation coverage"
57
57
  method_option :format, type: :string, desc: "Output format (text, json, yaml)", default: "text"
58
- method_option :exclude, type: :string, desc: "Comma-separated list of EXPRESS entity types to skip from coverage (e.g., TYPE,CONSTANT)"
58
+ method_option :exclude, type: :string, desc: "Comma-separated list of EXPRESS entity types to skip from coverage (e.g., TYPE,CONSTANT,TYPE:SELECT)"
59
+ method_option :output, type: :string, desc: "Output file path for JSON/YAML formats (defaults to coverage_report.json/yaml)"
59
60
  def coverage(*paths)
60
61
  Commands::Coverage.new(options).run(paths)
61
62
  end
@@ -275,33 +275,74 @@ module Expressir
275
275
  end
276
276
 
277
277
  def display_json_output(reports)
278
- say JSON.pretty_generate(build_structured_report(reports))
278
+ output_file = options[:output] || "coverage_report.json"
279
+ File.write(output_file, JSON.pretty_generate(build_structured_report(reports)))
280
+ say "JSON coverage report written to: #{output_file}"
279
281
  end
280
282
 
281
283
  def display_yaml_output(reports)
282
- say build_structured_report(reports).to_yaml
284
+ output_file = options[:output] || "coverage_report.yaml"
285
+ File.write(output_file, build_structured_report(reports).to_yaml)
286
+ say "YAML coverage report written to: #{output_file}"
283
287
  end
284
288
 
285
289
  # Parse and validate the skip_types option
286
290
  # @return [Array<String>] Array of validated entity type names
287
291
  def parse_skip_types
288
- skip_types_option = options["exclude"]
292
+ skip_types_option = options["exclude"] || options[:exclude]
289
293
  return [] unless skip_types_option
290
294
 
291
- # Split by comma and clean up whitespace
292
- requested_types = skip_types_option.split(",").map(&:strip).map(&:upcase)
295
+ # Handle both string (comma-separated) and array inputs
296
+ requested_types = if skip_types_option.is_a?(Array)
297
+ skip_types_option.map(&:to_s).map(&:strip).map(&:upcase)
298
+ else
299
+ skip_types_option.split(",").map(&:strip).map(&:upcase)
300
+ end
293
301
 
294
- # Validate against known entity types
295
- valid_types = Expressir::Coverage::ENTITY_TYPE_MAP.keys
296
- invalid_types = requested_types - valid_types
297
-
298
- unless invalid_types.empty?
299
- exit_with_error "Invalid entity types: #{invalid_types.join(', ')}. " \
300
- "Valid types are: #{valid_types.join(', ')}"
302
+ # Validate each type (supports both TYPE and TYPE:SUBTYPE formats)
303
+ requested_types.each do |type|
304
+ validate_skip_type(type)
301
305
  end
302
306
 
303
307
  requested_types
304
308
  end
309
+
310
+ # Validate a single skip type (supports TYPE:SUBTYPE and FUNCTION:SUBTYPE syntax)
311
+ # @param type [String] The type to validate
312
+ def validate_skip_type(type)
313
+ if type.include?(":")
314
+ # Handle TYPE:SUBTYPE and FUNCTION:SUBTYPE format
315
+ main_type, subtype = type.split(":", 2)
316
+
317
+ # Validate main type
318
+ unless Expressir::Coverage::ENTITY_TYPE_MAP.key?(main_type)
319
+ exit_with_error "Invalid entity type: #{main_type}. " \
320
+ "Valid types are: #{Expressir::Coverage::ENTITY_TYPE_MAP.keys.join(', ')}"
321
+ end
322
+
323
+ # For TYPE, validate subtype
324
+ if main_type == "TYPE"
325
+ unless Expressir::Coverage::TYPE_SUBTYPES.include?(subtype)
326
+ exit_with_error "Invalid TYPE subtype: #{subtype}. " \
327
+ "Valid TYPE subtypes are: #{Expressir::Coverage::TYPE_SUBTYPES.join(', ')}"
328
+ end
329
+ # For FUNCTION, validate subtype
330
+ elsif main_type == "FUNCTION"
331
+ unless subtype == "INNER"
332
+ exit_with_error "Invalid FUNCTION subtype: #{subtype}. " \
333
+ "Valid FUNCTION subtypes are: INNER"
334
+ end
335
+ else
336
+ exit_with_error "Subtype syntax (#{type}) is only supported for TYPE and FUNCTION entities"
337
+ end
338
+ else
339
+ # Handle simple type format
340
+ unless Expressir::Coverage::ENTITY_TYPE_MAP.key?(type)
341
+ exit_with_error "Invalid entity type: #{type}. " \
342
+ "Valid types are: #{Expressir::Coverage::ENTITY_TYPE_MAP.keys.join(', ')}"
343
+ end
344
+ end
345
+ end
305
346
  end
306
347
  end
307
348
  end
@@ -12,7 +12,50 @@ module Expressir
12
12
  "RULE" => "Expressir::Model::Declarations::Rule",
13
13
  "PROCEDURE" => "Expressir::Model::Declarations::Procedure",
14
14
  "SUBTYPE_CONSTRAINT" => "Expressir::Model::Declarations::SubtypeConstraint",
15
+ "PARAMETER" => "Expressir::Model::Declarations::Parameter",
16
+ "VARIABLE" => "Expressir::Model::Declarations::Variable",
17
+ "ATTRIBUTE" => "Expressir::Model::Declarations::Attribute",
18
+ "DERIVED_ATTRIBUTE" => "Expressir::Model::Declarations::DerivedAttribute",
19
+ "INVERSE_ATTRIBUTE" => "Expressir::Model::Declarations::InverseAttribute",
20
+ "UNIQUE_RULE" => "Expressir::Model::Declarations::UniqueRule",
21
+ "WHERE_RULE" => "Expressir::Model::Declarations::WhereRule",
22
+ "ENUMERATION_ITEM" => "Expressir::Model::DataTypes::EnumerationItem",
23
+ "INTERFACE" => "Expressir::Model::Declarations::Interface",
24
+ "INTERFACE_ITEM" => "Expressir::Model::Declarations::InterfaceItem",
25
+ "INTERFACED_ITEM" => "Expressir::Model::Declarations::InterfacedItem",
26
+ "SCHEMA_VERSION" => "Expressir::Model::Declarations::SchemaVersion",
27
+ "SCHEMA_VERSION_ITEM" => "Expressir::Model::Declarations::SchemaVersionItem",
15
28
  }.freeze
29
+
30
+ # Mapping of class names to EXPRESS entity type names (for proper formatting)
31
+ CLASS_TO_EXPRESS_TYPE_MAP = {
32
+ "Type" => "TYPE",
33
+ "Entity" => "ENTITY",
34
+ "Constant" => "CONSTANT",
35
+ "Function" => "FUNCTION",
36
+ "Rule" => "RULE",
37
+ "Procedure" => "PROCEDURE",
38
+ "SubtypeConstraint" => "SUBTYPE_CONSTRAINT",
39
+ "Parameter" => "PARAMETER",
40
+ "Variable" => "VARIABLE",
41
+ "Attribute" => "ATTRIBUTE",
42
+ "DerivedAttribute" => "DERIVED_ATTRIBUTE",
43
+ "InverseAttribute" => "INVERSE_ATTRIBUTE",
44
+ "UniqueRule" => "UNIQUE_RULE",
45
+ "WhereRule" => "WHERE_RULE",
46
+ "EnumerationItem" => "ENUMERATION_ITEM",
47
+ "Interface" => "INTERFACE",
48
+ "InterfaceItem" => "INTERFACE_ITEM",
49
+ "InterfacedItem" => "INTERFACED_ITEM",
50
+ "SchemaVersion" => "SCHEMA_VERSION",
51
+ "SchemaVersionItem" => "SCHEMA_VERSION_ITEM",
52
+ }.freeze
53
+
54
+ # Available TYPE subtypes based on data types
55
+ TYPE_SUBTYPES = %w[
56
+ AGGREGATE ARRAY BAG BINARY BOOLEAN ENUMERATION GENERIC GENERIC_ENTITY
57
+ INTEGER LIST LOGICAL NUMBER REAL SELECT SET STRING
58
+ ].freeze
16
59
  # Represents a documentation coverage report for EXPRESS schemas
17
60
  class Report
18
61
  attr_reader :repository, :schema_reports, :total_entities, :documented_entities,
@@ -173,8 +216,8 @@ module Expressir
173
216
  # Get class name (e.g., "Type" from "Expressir::Model::Declarations::Type")
174
217
  type_name = entity.class.name.split("::").last
175
218
 
176
- # Convert to EXPRESS convention (e.g., "TYPE")
177
- express_type = type_name.upcase
219
+ # Use proper mapping to EXPRESS convention
220
+ express_type = CLASS_TO_EXPRESS_TYPE_MAP[type_name] || type_name.upcase
178
221
 
179
222
  # Return structured format
180
223
  {
@@ -209,11 +252,35 @@ module Expressir
209
252
  end
210
253
  end
211
254
 
212
- # Find all entities in a schema
213
- # @param schema [Expressir::Model::Declarations::Schema] The schema to analyze
255
+ # Find all entities in a schema or repository
256
+ # @param schema_or_repo [Expressir::Model::Declarations::Schema, Expressir::Model::Repository] The schema or repository to analyze
214
257
  # @param skip_types [Array<String>] Array of entity type names to skip from coverage
215
258
  # @return [Array<Expressir::Model::ModelElement>] Array of entities
216
- def self.find_entities(schema, skip_types = [])
259
+ def self.find_entities(schema_or_repo, skip_types = [])
260
+ entities = []
261
+
262
+ # Handle both repository and schema inputs
263
+ if schema_or_repo.is_a?(Expressir::Model::Repository)
264
+ # If it's a repository, process all schemas
265
+ schema_or_repo.schemas.each do |schema|
266
+ entities.concat(find_entities_in_schema(schema))
267
+ end
268
+ else
269
+ # If it's a schema, process it directly
270
+ entities.concat(find_entities_in_schema(schema_or_repo))
271
+ end
272
+
273
+ # Filter out any nil elements and ensure all have IDs
274
+ entities = entities.compact.select { |e| e.respond_to?(:id) && e.id }
275
+
276
+ # Filter out skipped entity types
277
+ apply_exclusions(entities, skip_types)
278
+ end
279
+
280
+ # Find all entities in a single schema
281
+ # @param schema [Expressir::Model::Declarations::Schema] The schema to analyze
282
+ # @return [Array<Expressir::Model::ModelElement>] Array of entities
283
+ def self.find_entities_in_schema(schema)
217
284
  entities = []
218
285
 
219
286
  # Add all schema-level entities
@@ -224,26 +291,203 @@ module Expressir
224
291
  entities.concat(schema.rules) if schema.rules
225
292
  entities.concat(schema.procedures) if schema.procedures
226
293
  entities.concat(schema.subtype_constraints) if schema.subtype_constraints
294
+ entities.concat(schema.interfaces) if schema.interfaces
295
+
296
+ # Add nested entities recursively
297
+ entities.concat(find_nested_entities(schema))
298
+
299
+ entities
300
+ end
301
+
302
+ # Find all nested entities within a container (schema, entity, function, etc.)
303
+ # @param container [Expressir::Model::ModelElement] The container to search
304
+ # @return [Array<Expressir::Model::ModelElement>] Array of nested entities
305
+ def self.find_nested_entities(container)
306
+ entities = []
307
+
308
+ # Handle different container types
309
+ case container
310
+ when Expressir::Model::Declarations::Schema
311
+ # Schema-level nested entities
312
+ container.types&.each do |type|
313
+ entities.concat(find_nested_entities(type))
314
+ end
315
+ container.entities&.each do |entity|
316
+ entities.concat(find_nested_entities(entity))
317
+ end
318
+ container.functions&.each do |function|
319
+ entities.concat(find_nested_entities(function))
320
+ end
321
+ container.rules&.each do |rule|
322
+ entities.concat(find_nested_entities(rule))
323
+ end
324
+ container.procedures&.each do |procedure|
325
+ entities.concat(find_nested_entities(procedure))
326
+ end
327
+ container.interfaces&.each do |interface|
328
+ entities.concat(find_nested_entities(interface))
329
+ end
330
+
331
+ when Expressir::Model::Declarations::Type
332
+ # Type nested entities
333
+ if container.respond_to?(:enumeration_items) && container.enumeration_items
334
+ entities.concat(container.enumeration_items)
335
+ end
336
+
337
+ when Expressir::Model::Declarations::Entity
338
+ # Entity nested entities
339
+ entities.concat(container.attributes) if container.attributes
340
+ entities.concat(container.unique_rules) if container.unique_rules
341
+ entities.concat(container.where_rules) if container.where_rules
342
+
343
+ when Expressir::Model::Declarations::Function
344
+ # Function nested entities
345
+ entities.concat(container.parameters) if container.parameters
346
+ entities.concat(container.variables) if container.variables
347
+ entities.concat(container.constants) if container.constants
348
+ entities.concat(container.types) if container.types
349
+ entities.concat(container.entities) if container.entities
350
+ entities.concat(container.functions) if container.functions
351
+ entities.concat(container.procedures) if container.procedures
352
+ entities.concat(container.subtype_constraints) if container.subtype_constraints
353
+
354
+ # Recursively find nested entities in nested containers
355
+ container.types&.each { |type| entities.concat(find_nested_entities(type)) }
356
+ container.entities&.each { |entity| entities.concat(find_nested_entities(entity)) }
357
+ container.functions&.each { |function| entities.concat(find_nested_entities(function)) }
358
+ container.procedures&.each { |procedure| entities.concat(find_nested_entities(procedure)) }
359
+
360
+ when Expressir::Model::Declarations::Rule
361
+ # Rule nested entities
362
+ entities.concat(container.variables) if container.variables
363
+ entities.concat(container.constants) if container.constants
364
+ entities.concat(container.types) if container.types
365
+ entities.concat(container.entities) if container.entities
366
+ entities.concat(container.functions) if container.functions
367
+ entities.concat(container.procedures) if container.procedures
368
+ entities.concat(container.subtype_constraints) if container.subtype_constraints
369
+
370
+ # Recursively find nested entities in nested containers
371
+ container.types&.each { |type| entities.concat(find_nested_entities(type)) }
372
+ container.entities&.each { |entity| entities.concat(find_nested_entities(entity)) }
373
+ container.functions&.each { |function| entities.concat(find_nested_entities(function)) }
374
+ container.procedures&.each { |procedure| entities.concat(find_nested_entities(procedure)) }
375
+
376
+ when Expressir::Model::Declarations::Procedure
377
+ # Procedure nested entities
378
+ entities.concat(container.parameters) if container.parameters
379
+ entities.concat(container.variables) if container.variables
380
+ entities.concat(container.constants) if container.constants
381
+ entities.concat(container.types) if container.types
382
+ entities.concat(container.entities) if container.entities
383
+ entities.concat(container.functions) if container.functions
384
+ entities.concat(container.procedures) if container.procedures
385
+ entities.concat(container.subtype_constraints) if container.subtype_constraints
386
+
387
+ # Recursively find nested entities in nested containers
388
+ container.types&.each { |type| entities.concat(find_nested_entities(type)) }
389
+ container.entities&.each { |entity| entities.concat(find_nested_entities(entity)) }
390
+ container.functions&.each { |function| entities.concat(find_nested_entities(function)) }
391
+ container.procedures&.each { |procedure| entities.concat(find_nested_entities(procedure)) }
392
+
393
+ when Expressir::Model::Declarations::Interface
394
+ # Interface nested entities
395
+ entities.concat(container.items) if container.items
396
+ end
397
+
398
+ entities
399
+ end
400
+
401
+ # Apply exclusions to filter out entities based on skip_types (supports both simple and TYPE:SUBTYPE syntax)
402
+ # @param entities [Array<Expressir::Model::ModelElement>] The entities to filter
403
+ # @param exclusions [Array<String>] Array of entity type names to exclude from coverage
404
+ # @return [Array<Expressir::Model::ModelElement>] Filtered entities
405
+ def self.apply_exclusions(entities, exclusions)
406
+ filter_skipped_entities(entities, exclusions)
407
+ end
227
408
 
228
- # Add enumeration items from types (only if TYPE is not being skipped)
229
- unless skip_types.include?("TYPE")
230
- schema.types&.each do |type|
231
- if type.respond_to?(:enumeration_items) && type.enumeration_items
232
- entities.concat(type.enumeration_items)
409
+ # Filter out entities based on skip_types (supports both simple and TYPE:SUBTYPE syntax)
410
+ # @param entities [Array<Expressir::Model::ModelElement>] The entities to filter
411
+ # @param skip_types [Array<String>] Array of entity type names to skip from coverage
412
+ # @return [Array<Expressir::Model::ModelElement>] Filtered entities
413
+ def self.filter_skipped_entities(entities, skip_types)
414
+ return entities if skip_types.empty?
415
+
416
+ # Parse skip_types into simple types, TYPE subtypes, and FUNCTION subtypes
417
+ simple_skips = []
418
+ type_subtype_skips = []
419
+ function_subtype_skips = []
420
+
421
+ skip_types.each do |skip_type|
422
+ if skip_type.include?(":")
423
+ # Handle TYPE:SUBTYPE and FUNCTION:SUBTYPE format
424
+ main_type, subtype = skip_type.split(":", 2)
425
+ if main_type == "TYPE" && TYPE_SUBTYPES.include?(subtype)
426
+ type_subtype_skips << subtype
427
+ elsif main_type == "FUNCTION" && subtype == "INNER"
428
+ function_subtype_skips << subtype
233
429
  end
430
+ else
431
+ # Handle simple type format
432
+ simple_skips << skip_type
234
433
  end
235
434
  end
236
435
 
237
- # Filter out any nil elements and ensure all have IDs
238
- entities = entities.compact.select { |e| e.respond_to?(:id) && e.id }
436
+ # Filter entities
437
+ entities.reject do |entity|
438
+ entity_class = entity.class.name
439
+
440
+ # Check simple type exclusions
441
+ # Convert entity class to EXPRESS type name for comparison
442
+ class_name = entity_class.split("::").last
443
+ express_type = CLASS_TO_EXPRESS_TYPE_MAP[class_name] || class_name.upcase
444
+
445
+ if simple_skips.include?(express_type)
446
+ true
447
+ # Check TYPE subtype exclusions
448
+ elsif entity_class == "Expressir::Model::Declarations::Type" && type_subtype_skips.any?
449
+ entity_subtype = get_type_subtype(entity)
450
+ type_subtype_skips.include?(entity_subtype)
451
+ # Check FUNCTION:INNER exclusions
452
+ elsif entity_class == "Expressir::Model::Declarations::Function" && function_subtype_skips.include?("INNER")
453
+ is_inner_function?(entity)
454
+ else
455
+ false
456
+ end
457
+ end
458
+ end
239
459
 
240
- # Filter out skipped entity types
241
- if skip_types.any?
242
- skip_classes = skip_types.map { |type| ENTITY_TYPE_MAP[type] }.compact
243
- entities = entities.reject { |entity| skip_classes.include?(entity.class.name) }
460
+ # Get the subtype of a TYPE entity based on its underlying_type
461
+ # @param type_entity [Expressir::Model::Declarations::Type] The TYPE entity
462
+ # @return [String] The subtype name (e.g., "SELECT", "ENUMERATION")
463
+ def self.get_type_subtype(type_entity)
464
+ return nil unless type_entity.respond_to?(:underlying_type) && type_entity.underlying_type
465
+
466
+ # Get the class name of the underlying type
467
+ underlying_class = type_entity.underlying_type.class.name
468
+
469
+ # Extract the data type name (e.g., "Select" from "Expressir::Model::DataTypes::Select")
470
+ if underlying_class.start_with?("Expressir::Model::DataTypes::")
471
+ data_type_name = underlying_class.split("::").last
472
+ # Convert to uppercase (e.g., "Select" -> "SELECT")
473
+ data_type_name.upcase
474
+ else
475
+ # For other types, try to extract the last part of the class name
476
+ underlying_class.split("::").last&.upcase
244
477
  end
478
+ end
245
479
 
246
- entities
480
+ # Check if a function is an inner function (nested within another function, rule, or procedure)
481
+ # @param function_entity [Expressir::Model::Declarations::Function] The function entity to check
482
+ # @return [Boolean] True if the function is nested within another function, rule, or procedure
483
+ def self.is_inner_function?(function_entity)
484
+ return false unless function_entity.respond_to?(:parent) && function_entity.parent
485
+
486
+ # Check if the parent is a function, rule, or procedure (not a schema)
487
+ parent = function_entity.parent
488
+ parent.is_a?(Expressir::Model::Declarations::Function) ||
489
+ parent.is_a?(Expressir::Model::Declarations::Rule) ||
490
+ parent.is_a?(Expressir::Model::Declarations::Procedure)
247
491
  end
248
492
  end
249
493
  end
@@ -208,7 +208,8 @@ module Expressir
208
208
  private
209
209
 
210
210
  def format_repository(node)
211
- node.schemas&.map { |x| format(x) }&.join("\n\n")
211
+ result = node.schemas&.map { |x| format(x) }&.join("\n\n")
212
+ result ? "#{result}\n" : ""
212
213
  end
213
214
 
214
215
  def format_declarations_attribute(node)
@@ -1615,39 +1616,65 @@ module Expressir
1615
1616
  end
1616
1617
 
1617
1618
  def format_remark(node, remark)
1619
+ # Handle embedded remarks
1618
1620
  if remark.include?("\n")
1619
1621
  [
1620
1622
  [
1621
- "(*",
1622
- '"',
1623
+ "(*\"",
1623
1624
  node.path || node.id,
1624
- '"',
1625
+ "\"",
1625
1626
  ].join,
1626
1627
  remark,
1627
1628
  "*)",
1628
1629
  ].join("\n")
1629
1630
  else
1631
+ # Handle tail remarks
1630
1632
  [
1631
- "--",
1632
- '"',
1633
+ "--\"",
1633
1634
  node.path || node.id,
1634
- '"',
1635
- " ",
1635
+ "\" ",
1636
+ remark,
1637
+ ].join
1638
+ end
1639
+ end
1640
+
1641
+ def format_untagged_remark(remark)
1642
+ # Handle embedded remarks
1643
+ if remark.include?("\n")
1644
+ [
1645
+ "(*",
1646
+ remark,
1647
+ "*)",
1648
+ ].join("\n")
1649
+ else
1650
+ # Handle tail remarks
1651
+ [
1652
+ "-- ",
1636
1653
  remark,
1637
1654
  ].join
1638
1655
  end
1639
1656
  end
1640
1657
 
1641
1658
  def format_remarks(node)
1659
+ remarks = []
1660
+
1661
+ # Add tagged remarks
1642
1662
  if node.class.method_defined?(:remarks) && !@no_remarks &&
1643
1663
  !node.remarks.nil?
1644
-
1645
- node.remarks.map do |remark|
1664
+ remarks.concat(node.remarks.map do |remark|
1646
1665
  format_remark(node, remark)
1647
- end
1648
- else
1649
- []
1666
+ end)
1667
+ end
1668
+
1669
+ # Add untagged remarks
1670
+ if node.respond_to?(:untagged_remarks) && !@no_remarks &&
1671
+ !node.untagged_remarks.nil?
1672
+ remarks.concat(node.untagged_remarks.map do |remark|
1673
+ format_untagged_remark(remark)
1674
+ end)
1650
1675
  end
1676
+
1677
+ remarks
1651
1678
  end
1652
1679
 
1653
1680
  def format_scope_remarks(node)
@@ -271,32 +271,67 @@ module Expressir
271
271
  remark_tokens = remark_tokens.reject { |x| @attached_remark_tokens.include?(x) }
272
272
 
273
273
  # parse remarks, find remark targets
274
- tagged_remark_tokens = remark_tokens.map do |span|
274
+ tagged_remark_tokens = []
275
+ untagged_remark_tokens = []
276
+
277
+ remark_tokens.each do |span|
275
278
  text = @source[span[0]..span[1] - 1]
276
- _, remark_tag, remark_text = if text.start_with?("--")
277
- text.match(/^--"([^"]*)"(.*)$/).to_a
278
- else
279
- text.match(/^\(\*"([^"]*)"(.*)\*\)$/m).to_a
280
- end
281
-
282
- if remark_tag
283
- remark_target = find_remark_target(node, remark_tag)
284
- end
285
- if remark_text
286
- remark_text = remark_text.strip.force_encoding("UTF-8")
279
+ remark_type = if text.start_with?("--")
280
+ :tail
281
+ else
282
+ :embedded
283
+ end
284
+
285
+ if text.start_with?("--\"") && text.include?("\"")
286
+ # Tagged tail remark: --"tag" content
287
+ quote_end = text.index("\"", 3)
288
+ if quote_end
289
+ remark_target_path = text[3...quote_end]
290
+ remark_text = text[(quote_end + 1)..].strip.force_encoding("UTF-8")
291
+ remark_target = find_remark_target(node, remark_target_path)
292
+ if remark_target
293
+ tagged_remark_tokens << [span, remark_target, remark_text]
294
+ end
295
+ end
296
+ elsif text.start_with?("(*\"") && text.include?("\"")
297
+ # Tagged embedded remark: (*"tag" content *)
298
+ quote_end = text.index("\"", 3)
299
+ if quote_end
300
+ remark_target_path = text[3...quote_end]
301
+ remark_text = text[(quote_end + 1)...-2].strip.force_encoding("UTF-8")
302
+ remark_target = find_remark_target(node, remark_target_path)
303
+ if remark_target
304
+ tagged_remark_tokens << [span, remark_target, remark_text]
305
+ end
306
+ end
307
+ elsif text.start_with?("--")
308
+ # Untagged tail remark: -- content
309
+ untagged_text = text[2..].strip.force_encoding("UTF-8")
310
+ untagged_remark_tokens << [span, untagged_text, remark_type]
311
+ else
312
+ # Untagged embedded remark: (* content *)
313
+ untagged_text = text[2...-2].strip.force_encoding("UTF-8")
314
+ untagged_remark_tokens << [span, untagged_text, remark_type]
287
315
  end
316
+ end
288
317
 
289
- [span, remark_target, remark_text]
290
- end.select { |x| x[1] }
291
-
318
+ # Attach tagged remarks
292
319
  tagged_remark_tokens.each do |span, remark_target, remark_text|
293
- # attach remark
294
320
  remark_target.remarks ||= []
295
321
  remark_target.remarks << remark_text
296
-
297
- # mark remark as attached, so that it is not attached again at higher nesting level
298
322
  @attached_remark_tokens << span
299
323
  end
324
+
325
+ # Attach untagged remarks to the current node if it supports them
326
+ # All ModelElements support untagged remarks, but we may get Arrays here
327
+ if node.respond_to?(:untagged_remarks) && !untagged_remark_tokens.empty?
328
+ node.untagged_remarks ||= []
329
+ untagged_remark_tokens.each do |span, untagged_text, _remark_type|
330
+ # Handle both embedded and tail remarks
331
+ node.untagged_remarks << untagged_text
332
+ @attached_remark_tokens << span
333
+ end
334
+ end
300
335
  end
301
336
 
302
337
  def visit_attribute_ref(ctx)
@@ -5,11 +5,13 @@ module Expressir
5
5
  mod.attribute :id, :string
6
6
  mod.attribute :remarks, :string, collection: true
7
7
  mod.attribute :remark_items, ::Expressir::Model::Declarations::RemarkItem, collection: true
8
+ mod.attribute :untagged_remarks, :string, collection: true
8
9
 
9
10
  mod.key_value do
10
11
  map "id", to: :id
11
12
  map "remarks", to: :remarks
12
13
  map "remark_items", to: :remark_items
14
+ map "untagged_remarks", to: :untagged_remarks
13
15
  end
14
16
  end
15
17
  end
@@ -13,6 +13,7 @@ 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
17
 
17
18
  # TODO: Add basic mappings that can be inherited by all subclasses
18
19
  key_value do
@@ -1,72 +1,95 @@
1
- require_relative "model/model_element"
2
- require_relative "model/cache"
3
- require_relative "model/identifier"
4
- require_relative "model/repository"
1
+ # This file is kept for backward compatibility and to ensure all model classes are loaded
2
+ # when explicitly requiring 'expressir/model'. The actual autoload definitions are in the main
3
+ # expressir.rb file.
5
4
 
6
- require_relative "model/data_types/aggregate"
7
- require_relative "model/data_types/array"
8
- require_relative "model/data_types/bag"
9
- require_relative "model/data_types/binary"
10
- require_relative "model/data_types/boolean"
11
- require_relative "model/data_types/enumeration"
12
- require_relative "model/data_types/enumeration_item"
13
- require_relative "model/data_types/generic_entity"
14
- require_relative "model/data_types/generic"
15
- require_relative "model/data_types/integer"
16
- require_relative "model/data_types/list"
17
- require_relative "model/data_types/logical"
18
- require_relative "model/data_types/number"
19
- require_relative "model/data_types/real"
20
- require_relative "model/data_types/set"
21
- require_relative "model/data_types/select"
22
- require_relative "model/data_types/string"
23
- require_relative "model/declarations/attribute"
24
- require_relative "model/declarations/constant"
25
- require_relative "model/declarations/entity"
26
- require_relative "model/declarations/function"
27
- require_relative "model/declarations/interface"
28
- require_relative "model/declarations/interface_item"
29
- require_relative "model/declarations/interfaced_item"
30
- require_relative "model/declarations/parameter"
31
- require_relative "model/declarations/procedure"
32
- require_relative "model/declarations/remark_item"
33
- require_relative "model/declarations/rule"
34
- require_relative "model/declarations/schema"
35
- require_relative "model/declarations/schema_version"
36
- require_relative "model/declarations/schema_version_item"
37
- require_relative "model/declarations/subtype_constraint"
38
- require_relative "model/declarations/type"
39
- require_relative "model/declarations/unique_rule"
40
- require_relative "model/declarations/variable"
41
- require_relative "model/declarations/where_rule"
42
- require_relative "model/expressions/aggregate_initializer"
43
- require_relative "model/expressions/aggregate_initializer_item"
44
- require_relative "model/expressions/binary_expression"
45
- require_relative "model/expressions/entity_constructor"
46
- require_relative "model/expressions/function_call"
47
- require_relative "model/expressions/interval"
48
- require_relative "model/expressions/query_expression"
49
- require_relative "model/expressions/unary_expression"
50
- require_relative "model/literals/binary"
51
- require_relative "model/literals/integer"
52
- require_relative "model/literals/logical"
53
- require_relative "model/literals/real"
54
- require_relative "model/literals/string"
55
- require_relative "model/references/attribute_reference"
56
- require_relative "model/references/group_reference"
57
- require_relative "model/references/index_reference"
58
- require_relative "model/references/simple_reference"
59
- require_relative "model/statements/alias"
60
- require_relative "model/statements/assignment"
61
- require_relative "model/statements/case"
62
- require_relative "model/statements/case_action"
63
- require_relative "model/statements/compound"
64
- require_relative "model/statements/escape"
65
- require_relative "model/statements/if"
66
- require_relative "model/statements/null"
67
- require_relative "model/statements/procedure_call"
68
- require_relative "model/statements/repeat"
69
- require_relative "model/statements/return"
70
- require_relative "model/statements/skip"
71
- require_relative "model/supertype_expressions/binary_supertype_expression"
72
- require_relative "model/supertype_expressions/oneof_supertype_expression"
5
+ # Ensure all model classes are loaded by referencing them
6
+ # This triggers the autoload mechanism for each class
7
+
8
+ # Core model classes
9
+ Expressir::Model::ModelElement
10
+ Expressir::Model::Cache
11
+ Expressir::Model::Identifier
12
+ Expressir::Model::Repository
13
+
14
+ # Data types
15
+ Expressir::Model::DataTypes::Aggregate
16
+ Expressir::Model::DataTypes::Array
17
+ Expressir::Model::DataTypes::Bag
18
+ Expressir::Model::DataTypes::Binary
19
+ Expressir::Model::DataTypes::Boolean
20
+ Expressir::Model::DataTypes::Enumeration
21
+ Expressir::Model::DataTypes::EnumerationItem
22
+ Expressir::Model::DataTypes::GenericEntity
23
+ Expressir::Model::DataTypes::Generic
24
+ Expressir::Model::DataTypes::Integer
25
+ Expressir::Model::DataTypes::List
26
+ Expressir::Model::DataTypes::Logical
27
+ Expressir::Model::DataTypes::Number
28
+ Expressir::Model::DataTypes::Real
29
+ Expressir::Model::DataTypes::Select
30
+ Expressir::Model::DataTypes::Set
31
+ Expressir::Model::DataTypes::String
32
+
33
+ # Declarations
34
+ Expressir::Model::Declarations::Attribute
35
+ Expressir::Model::Declarations::Constant
36
+ Expressir::Model::Declarations::DerivedAttribute
37
+ Expressir::Model::Declarations::Entity
38
+ Expressir::Model::Declarations::Function
39
+ Expressir::Model::Declarations::Interface
40
+ Expressir::Model::Declarations::InterfaceItem
41
+ Expressir::Model::Declarations::InterfacedItem
42
+ Expressir::Model::Declarations::InverseAttribute
43
+ Expressir::Model::Declarations::Parameter
44
+ Expressir::Model::Declarations::Procedure
45
+ Expressir::Model::Declarations::RemarkItem
46
+ Expressir::Model::Declarations::Rule
47
+ Expressir::Model::Declarations::Schema
48
+ Expressir::Model::Declarations::SchemaVersion
49
+ Expressir::Model::Declarations::SchemaVersionItem
50
+ Expressir::Model::Declarations::SubtypeConstraint
51
+ Expressir::Model::Declarations::Type
52
+ Expressir::Model::Declarations::UniqueRule
53
+ Expressir::Model::Declarations::Variable
54
+ Expressir::Model::Declarations::WhereRule
55
+
56
+ # Expressions
57
+ Expressir::Model::Expressions::AggregateInitializer
58
+ Expressir::Model::Expressions::AggregateInitializerItem
59
+ Expressir::Model::Expressions::BinaryExpression
60
+ Expressir::Model::Expressions::EntityConstructor
61
+ Expressir::Model::Expressions::FunctionCall
62
+ Expressir::Model::Expressions::Interval
63
+ Expressir::Model::Expressions::QueryExpression
64
+ Expressir::Model::Expressions::UnaryExpression
65
+
66
+ # Literals
67
+ Expressir::Model::Literals::Binary
68
+ Expressir::Model::Literals::Integer
69
+ Expressir::Model::Literals::Logical
70
+ Expressir::Model::Literals::Real
71
+ Expressir::Model::Literals::String
72
+
73
+ # References
74
+ Expressir::Model::References::AttributeReference
75
+ Expressir::Model::References::GroupReference
76
+ Expressir::Model::References::IndexReference
77
+ Expressir::Model::References::SimpleReference
78
+
79
+ # Statements
80
+ Expressir::Model::Statements::Alias
81
+ Expressir::Model::Statements::Assignment
82
+ Expressir::Model::Statements::Case
83
+ Expressir::Model::Statements::CaseAction
84
+ Expressir::Model::Statements::Compound
85
+ Expressir::Model::Statements::Escape
86
+ Expressir::Model::Statements::If
87
+ Expressir::Model::Statements::Null
88
+ Expressir::Model::Statements::ProcedureCall
89
+ Expressir::Model::Statements::Repeat
90
+ Expressir::Model::Statements::Return
91
+ Expressir::Model::Statements::Skip
92
+
93
+ # Supertype expressions
94
+ Expressir::Model::SupertypeExpressions::BinarySupertypeExpression
95
+ Expressir::Model::SupertypeExpressions::OneofSupertypeExpression
@@ -1,3 +1,3 @@
1
1
  module Expressir
2
- VERSION = "2.1.19".freeze
2
+ VERSION = "2.1.21".freeze
3
3
  end
data/lib/expressir.rb CHANGED
@@ -1,4 +1,3 @@
1
- require "zeitwerk"
2
1
  require_relative "expressir/version"
3
2
  require_relative "expressir/cli"
4
3
  require_relative "expressir/config"
@@ -36,13 +35,129 @@ module Expressir
36
35
  def self.root_path
37
36
  @root_path ||= Pathname.new(Expressir.root)
38
37
  end
39
- end
40
38
 
41
- loader = Zeitwerk::Loader.for_gem
42
- loader.setup
39
+ # Autoload for Express module classes
40
+ module Express
41
+ autoload :Cache, "expressir/express/cache"
42
+ autoload :Error, "expressir/express/error"
43
+ autoload :Formatter, "expressir/express/formatter"
44
+ autoload :HyperlinkFormatter, "expressir/express/hyperlink_formatter"
45
+ autoload :ModelVisitor, "expressir/express/model_visitor"
46
+ autoload :Parser, "expressir/express/parser"
47
+ autoload :ResolveReferencesModelVisitor, "expressir/express/resolve_references_model_visitor"
48
+ autoload :SchemaHeadFormatter, "expressir/express/schema_head_formatter"
49
+ autoload :Visitor, "expressir/express/visitor"
50
+ end
51
+
52
+ # Autoload for Model module classes
53
+ module Model
54
+ autoload :ModelElement, "expressir/model/model_element"
55
+ autoload :Cache, "expressir/model/cache"
56
+ autoload :Identifier, "expressir/model/identifier"
57
+ autoload :Repository, "expressir/model/repository"
58
+
59
+ module DataTypes
60
+ autoload :Aggregate, "expressir/model/data_types/aggregate"
61
+ autoload :Array, "expressir/model/data_types/array"
62
+ autoload :Bag, "expressir/model/data_types/bag"
63
+ autoload :Binary, "expressir/model/data_types/binary"
64
+ autoload :Boolean, "expressir/model/data_types/boolean"
65
+ autoload :Enumeration, "expressir/model/data_types/enumeration"
66
+ autoload :EnumerationItem, "expressir/model/data_types/enumeration_item"
67
+ autoload :GenericEntity, "expressir/model/data_types/generic_entity"
68
+ autoload :Generic, "expressir/model/data_types/generic"
69
+ autoload :Integer, "expressir/model/data_types/integer"
70
+ autoload :List, "expressir/model/data_types/list"
71
+ autoload :Logical, "expressir/model/data_types/logical"
72
+ autoload :Number, "expressir/model/data_types/number"
73
+ autoload :Real, "expressir/model/data_types/real"
74
+ autoload :Select, "expressir/model/data_types/select"
75
+ autoload :Set, "expressir/model/data_types/set"
76
+ autoload :String, "expressir/model/data_types/string"
77
+ end
78
+
79
+ module Declarations
80
+ autoload :Attribute, "expressir/model/declarations/attribute"
81
+ autoload :Constant, "expressir/model/declarations/constant"
82
+ autoload :DerivedAttribute, "expressir/model/declarations/derived_attribute"
83
+ autoload :Entity, "expressir/model/declarations/entity"
84
+ autoload :Function, "expressir/model/declarations/function"
85
+ autoload :Interface, "expressir/model/declarations/interface"
86
+ autoload :InterfaceItem, "expressir/model/declarations/interface_item"
87
+ autoload :InterfacedItem, "expressir/model/declarations/interfaced_item"
88
+ autoload :InverseAttribute, "expressir/model/declarations/inverse_attribute"
89
+ autoload :Parameter, "expressir/model/declarations/parameter"
90
+ autoload :Procedure, "expressir/model/declarations/procedure"
91
+ autoload :RemarkItem, "expressir/model/declarations/remark_item"
92
+ autoload :Rule, "expressir/model/declarations/rule"
93
+ autoload :Schema, "expressir/model/declarations/schema"
94
+ autoload :SchemaVersion, "expressir/model/declarations/schema_version"
95
+ autoload :SchemaVersionItem, "expressir/model/declarations/schema_version_item"
96
+ autoload :SubtypeConstraint, "expressir/model/declarations/subtype_constraint"
97
+ autoload :Type, "expressir/model/declarations/type"
98
+ autoload :UniqueRule, "expressir/model/declarations/unique_rule"
99
+ autoload :Variable, "expressir/model/declarations/variable"
100
+ autoload :WhereRule, "expressir/model/declarations/where_rule"
101
+ end
43
102
 
44
- Dir[File.join(__dir__, "expressir", "express", "*.rb")].sort.each do |fea|
45
- require fea
103
+ module Expressions
104
+ autoload :AggregateInitializer, "expressir/model/expressions/aggregate_initializer"
105
+ autoload :AggregateInitializerItem, "expressir/model/expressions/aggregate_initializer_item"
106
+ autoload :BinaryExpression, "expressir/model/expressions/binary_expression"
107
+ autoload :EntityConstructor, "expressir/model/expressions/entity_constructor"
108
+ autoload :FunctionCall, "expressir/model/expressions/function_call"
109
+ autoload :Interval, "expressir/model/expressions/interval"
110
+ autoload :QueryExpression, "expressir/model/expressions/query_expression"
111
+ autoload :UnaryExpression, "expressir/model/expressions/unary_expression"
112
+ end
113
+
114
+ module Literals
115
+ autoload :Binary, "expressir/model/literals/binary"
116
+ autoload :Integer, "expressir/model/literals/integer"
117
+ autoload :Logical, "expressir/model/literals/logical"
118
+ autoload :Real, "expressir/model/literals/real"
119
+ autoload :String, "expressir/model/literals/string"
120
+ end
121
+
122
+ module References
123
+ autoload :AttributeReference, "expressir/model/references/attribute_reference"
124
+ autoload :GroupReference, "expressir/model/references/group_reference"
125
+ autoload :IndexReference, "expressir/model/references/index_reference"
126
+ autoload :SimpleReference, "expressir/model/references/simple_reference"
127
+ end
128
+
129
+ module Statements
130
+ autoload :Alias, "expressir/model/statements/alias"
131
+ autoload :Assignment, "expressir/model/statements/assignment"
132
+ autoload :Case, "expressir/model/statements/case"
133
+ autoload :CaseAction, "expressir/model/statements/case_action"
134
+ autoload :Compound, "expressir/model/statements/compound"
135
+ autoload :Escape, "expressir/model/statements/escape"
136
+ autoload :If, "expressir/model/statements/if"
137
+ autoload :Null, "expressir/model/statements/null"
138
+ autoload :ProcedureCall, "expressir/model/statements/procedure_call"
139
+ autoload :Repeat, "expressir/model/statements/repeat"
140
+ autoload :Return, "expressir/model/statements/return"
141
+ autoload :Skip, "expressir/model/statements/skip"
142
+ end
143
+
144
+ module SupertypeExpressions
145
+ autoload :BinarySupertypeExpression, "expressir/model/supertype_expressions/binary_supertype_expression"
146
+ autoload :OneofSupertypeExpression, "expressir/model/supertype_expressions/oneof_supertype_expression"
147
+ end
148
+ end
149
+
150
+ # Autoload for Commands module classes
151
+ module Commands
152
+ autoload :Base, "expressir/commands/base"
153
+ autoload :Benchmark, "expressir/commands/benchmark"
154
+ autoload :BenchmarkCache, "expressir/commands/benchmark_cache"
155
+ autoload :Clean, "expressir/commands/clean"
156
+ autoload :Coverage, "expressir/commands/coverage"
157
+ autoload :Format, "expressir/commands/format"
158
+ autoload :Validate, "expressir/commands/validate"
159
+ autoload :Version, "expressir/commands/version"
160
+ end
46
161
  end
47
162
 
48
163
  require_relative "expressir/model"
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.19
4
+ version: 2.1.21
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-06-04 00:00:00.000000000 Z
11
+ date: 2025-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -136,20 +136,6 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '1.0'
139
- - !ruby/object:Gem::Dependency
140
- name: zeitwerk
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '2.6'
146
- type: :runtime
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '2.6'
153
139
  description: Expressir ("EXPRESS in Ruby") is a Ruby parser for EXPRESS and a set
154
140
  of tools for accessing EXPRESS data models.
155
141
  email: