expressir 2.1.20 → 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 +4 -4
- data/.rubocop_todo.yml +37 -13
- data/README.adoc +36 -0
- data/lib/expressir/commands/coverage.rb +9 -3
- data/lib/expressir/coverage.rb +21 -2
- data/lib/expressir/express/formatter.rb +40 -13
- data/lib/expressir/express/visitor.rb +53 -18
- data/lib/expressir/model/identifier.rb +2 -0
- data/lib/expressir/model/model_element.rb +1 -0
- data/lib/expressir/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5523a9cdb1e5b8168a0d2d7262cdd8a5e849b066a3eeaaad90a3bcb3a640fe38
|
4
|
+
data.tar.gz: 293acbebeecc50a22ba8bc56aa8413f7e156dac17fa4fa872380aff5a9bf320c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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-05
|
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
|
@@ -27,11 +27,25 @@ Lint/DuplicateBranch:
|
|
27
27
|
Exclude:
|
28
28
|
- 'lib/expressir/coverage.rb'
|
29
29
|
|
30
|
+
# Offense count: 1
|
31
|
+
# This cop supports safe autocorrection (--autocorrect).
|
32
|
+
Lint/ScriptPermission:
|
33
|
+
Exclude:
|
34
|
+
- 'update_yaml_fixtures.rb'
|
35
|
+
|
30
36
|
# Offense count: 3
|
31
37
|
Lint/ShadowingOuterLocalVariable:
|
32
38
|
Exclude:
|
33
39
|
- 'lib/expressir/express/visitor.rb'
|
34
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
|
+
|
35
49
|
# Offense count: 2
|
36
50
|
# This cop supports safe autocorrection (--autocorrect).
|
37
51
|
# Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
|
@@ -41,7 +55,7 @@ Lint/UnusedMethodArgument:
|
|
41
55
|
- 'lib/expressir/express/cache.rb'
|
42
56
|
- 'lib/expressir/express/parser.rb'
|
43
57
|
|
44
|
-
# Offense count:
|
58
|
+
# Offense count: 76
|
45
59
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
46
60
|
Metrics/AbcSize:
|
47
61
|
Exclude:
|
@@ -60,13 +74,13 @@ Metrics/AbcSize:
|
|
60
74
|
- 'lib/expressir/model/declarations/schema.rb'
|
61
75
|
- 'lib/expressir/model/model_element.rb'
|
62
76
|
|
63
|
-
# Offense count:
|
77
|
+
# Offense count: 2
|
64
78
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
65
79
|
# AllowedMethods: refine
|
66
80
|
Metrics/BlockLength:
|
67
81
|
Max: 143
|
68
82
|
|
69
|
-
# Offense count:
|
83
|
+
# Offense count: 56
|
70
84
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
71
85
|
Metrics/CyclomaticComplexity:
|
72
86
|
Exclude:
|
@@ -81,12 +95,12 @@ Metrics/CyclomaticComplexity:
|
|
81
95
|
- 'lib/expressir/model/model_element.rb'
|
82
96
|
- 'spec/support/model_element_helper.rb'
|
83
97
|
|
84
|
-
# Offense count:
|
98
|
+
# Offense count: 100
|
85
99
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
86
100
|
Metrics/MethodLength:
|
87
101
|
Max: 82
|
88
102
|
|
89
|
-
# Offense count:
|
103
|
+
# Offense count: 44
|
90
104
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
91
105
|
Metrics/PerceivedComplexity:
|
92
106
|
Exclude:
|
@@ -98,19 +112,29 @@ Metrics/PerceivedComplexity:
|
|
98
112
|
- 'lib/expressir/model/declarations/schema.rb'
|
99
113
|
- 'lib/expressir/model/model_element.rb'
|
100
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
|
+
|
101
126
|
# Offense count: 5
|
102
127
|
Performance/FixedSize:
|
103
128
|
Exclude:
|
104
129
|
- 'lib/expressir/express/formatter.rb'
|
105
130
|
|
106
|
-
# Offense count: 6
|
107
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
108
|
-
# Configuration parameters: AllowRegexpMatch.
|
109
|
-
Performance/RedundantEqualityComparisonBlock:
|
110
|
-
Exclude:
|
111
|
-
- 'spec/expressir/coverage_spec.rb'
|
112
|
-
|
113
131
|
# Offense count: 1
|
114
132
|
Style/MissingRespondToMissing:
|
115
133
|
Exclude:
|
116
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
@@ -344,6 +344,42 @@ expressir coverage --exclude=TYPE:SELECT schemas/resources/action_schema/action_
|
|
344
344
|
expressir coverage --exclude=TYPE:SELECT,TYPE:ENUMERATION schemas/resources/action_schema/action_schema.exp
|
345
345
|
----
|
346
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
|
+
|
347
383
|
Valid TYPE subtypes that can be excluded:
|
348
384
|
|
349
385
|
`AGGREGATE`:: Aggregate type
|
@@ -307,11 +307,11 @@ module Expressir
|
|
307
307
|
requested_types
|
308
308
|
end
|
309
309
|
|
310
|
-
# Validate a single skip type (supports TYPE:SUBTYPE syntax)
|
310
|
+
# Validate a single skip type (supports TYPE:SUBTYPE and FUNCTION:SUBTYPE syntax)
|
311
311
|
# @param type [String] The type to validate
|
312
312
|
def validate_skip_type(type)
|
313
313
|
if type.include?(":")
|
314
|
-
# Handle TYPE:SUBTYPE format
|
314
|
+
# Handle TYPE:SUBTYPE and FUNCTION:SUBTYPE format
|
315
315
|
main_type, subtype = type.split(":", 2)
|
316
316
|
|
317
317
|
# Validate main type
|
@@ -326,8 +326,14 @@ module Expressir
|
|
326
326
|
exit_with_error "Invalid TYPE subtype: #{subtype}. " \
|
327
327
|
"Valid TYPE subtypes are: #{Expressir::Coverage::TYPE_SUBTYPES.join(', ')}"
|
328
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
|
329
335
|
else
|
330
|
-
exit_with_error "Subtype syntax (#{type}) is only supported for TYPE entities"
|
336
|
+
exit_with_error "Subtype syntax (#{type}) is only supported for TYPE and FUNCTION entities"
|
331
337
|
end
|
332
338
|
else
|
333
339
|
# Handle simple type format
|
data/lib/expressir/coverage.rb
CHANGED
@@ -413,16 +413,19 @@ module Expressir
|
|
413
413
|
def self.filter_skipped_entities(entities, skip_types)
|
414
414
|
return entities if skip_types.empty?
|
415
415
|
|
416
|
-
# Parse skip_types into simple types and
|
416
|
+
# Parse skip_types into simple types, TYPE subtypes, and FUNCTION subtypes
|
417
417
|
simple_skips = []
|
418
418
|
type_subtype_skips = []
|
419
|
+
function_subtype_skips = []
|
419
420
|
|
420
421
|
skip_types.each do |skip_type|
|
421
422
|
if skip_type.include?(":")
|
422
|
-
# Handle TYPE:SUBTYPE format
|
423
|
+
# Handle TYPE:SUBTYPE and FUNCTION:SUBTYPE format
|
423
424
|
main_type, subtype = skip_type.split(":", 2)
|
424
425
|
if main_type == "TYPE" && TYPE_SUBTYPES.include?(subtype)
|
425
426
|
type_subtype_skips << subtype
|
427
|
+
elsif main_type == "FUNCTION" && subtype == "INNER"
|
428
|
+
function_subtype_skips << subtype
|
426
429
|
end
|
427
430
|
else
|
428
431
|
# Handle simple type format
|
@@ -445,6 +448,9 @@ module Expressir
|
|
445
448
|
elsif entity_class == "Expressir::Model::Declarations::Type" && type_subtype_skips.any?
|
446
449
|
entity_subtype = get_type_subtype(entity)
|
447
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)
|
448
454
|
else
|
449
455
|
false
|
450
456
|
end
|
@@ -470,5 +476,18 @@ module Expressir
|
|
470
476
|
underlying_class.split("::").last&.upcase
|
471
477
|
end
|
472
478
|
end
|
479
|
+
|
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)
|
491
|
+
end
|
473
492
|
end
|
474
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
|
-
|
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 =
|
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
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
if
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
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
|
-
|
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
|
data/lib/expressir/version.rb
CHANGED
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.
|
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-
|
11
|
+
date: 2025-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base64
|