expressir 2.1.22 → 2.1.24
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.yml +9 -9
- data/.rubocop_todo.yml +62 -64
- data/Gemfile +2 -2
- data/README.adoc +202 -5
- data/bin/rspec +2 -1
- data/docs/liquid_drops.adoc +1 -1
- data/expressir.gemspec +1 -3
- data/lib/expressir/benchmark.rb +6 -3
- data/lib/expressir/cli.rb +24 -12
- data/lib/expressir/commands/benchmark.rb +7 -16
- data/lib/expressir/commands/benchmark_cache.rb +9 -17
- data/lib/expressir/commands/coverage.rb +43 -42
- data/lib/expressir/coverage.rb +41 -15
- data/lib/expressir/express/cache.rb +2 -1
- data/lib/expressir/express/formatter.rb +54 -12
- data/lib/expressir/express/hyperlink_formatter.rb +2 -1
- data/lib/expressir/express/parser.rb +329 -112
- data/lib/expressir/express/schema_head_formatter.rb +2 -1
- data/lib/expressir/express/visitor.rb +114 -51
- data/lib/expressir/model/declarations/entity.rb +2 -1
- data/lib/expressir/model/declarations/informal_proposition_rule.rb +24 -0
- data/lib/expressir/model/declarations/rule.rb +2 -1
- data/lib/expressir/model/declarations/schema.rb +4 -1
- data/lib/expressir/model/declarations/type.rb +2 -1
- data/lib/expressir/model/identifier.rb +2 -1
- data/lib/expressir/model/literals/string.rb +2 -1
- data/lib/expressir/model/model_element.rb +84 -145
- data/lib/expressir/model/repository.rb +2 -1
- data/lib/expressir/schema_manifest.rb +150 -0
- data/lib/expressir/schema_manifest_entry.rb +17 -0
- data/lib/expressir/version.rb +1 -1
- data/lib/expressir.rb +29 -12
- metadata +9 -6
@@ -47,7 +47,7 @@ module Expressir
|
|
47
47
|
elsif File.extname(path).downcase == ".exp"
|
48
48
|
handle_express_file(path, reports, ignored_files)
|
49
49
|
elsif [".yml", ".yaml"].include?(File.extname(path).downcase)
|
50
|
-
|
50
|
+
handle_schema_manifest(path, reports, ignored_files)
|
51
51
|
else
|
52
52
|
say "Unsupported file type: #{path}"
|
53
53
|
end
|
@@ -80,7 +80,11 @@ module Expressir
|
|
80
80
|
progress.increment
|
81
81
|
end
|
82
82
|
skip_types = parse_skip_types
|
83
|
-
report = Expressir::Coverage::Report.from_repository(
|
83
|
+
report = Expressir::Coverage::Report.from_repository(
|
84
|
+
repository,
|
85
|
+
skip_types,
|
86
|
+
ignored_files,
|
87
|
+
)
|
84
88
|
reports << report
|
85
89
|
rescue StandardError => e
|
86
90
|
say "Error processing directory #{path}: #{e.message}"
|
@@ -92,42 +96,22 @@ module Expressir
|
|
92
96
|
begin
|
93
97
|
# For a single file, we don't need a progress bar
|
94
98
|
skip_types = parse_skip_types
|
95
|
-
report = Expressir::Coverage::Report.from_file(path, skip_types,
|
99
|
+
report = Expressir::Coverage::Report.from_file(path, skip_types,
|
100
|
+
ignored_files)
|
96
101
|
reports << report
|
97
102
|
rescue StandardError => e
|
98
103
|
say "Error processing file #{path}: #{e.message}"
|
99
104
|
end
|
100
105
|
end
|
101
106
|
|
102
|
-
def
|
103
|
-
say "Processing
|
107
|
+
def handle_schema_manifest(path, reports, ignored_files)
|
108
|
+
say "Processing schema manifest: #{path}"
|
104
109
|
begin
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
# Handle the nested structure with schema name keys and path values
|
112
|
-
if schemas_data.is_a?(Hash)
|
113
|
-
schema_files = schemas_data.values.map do |schema_data|
|
114
|
-
if schema_data.is_a?(Hash) && schema_data["path"]
|
115
|
-
# Make path relative to the manifest location
|
116
|
-
File.expand_path(schema_data["path"], manifest_dir)
|
117
|
-
end
|
118
|
-
end.compact
|
119
|
-
|
120
|
-
say "Found #{schema_files.size} schema files to process"
|
121
|
-
else
|
122
|
-
# If it's a direct array of paths (old format)
|
123
|
-
schema_files = schemas_data
|
124
|
-
end
|
125
|
-
elsif schema_list.is_a?(Array)
|
126
|
-
schema_files = schema_list
|
127
|
-
else
|
128
|
-
say "Invalid YAML format. Expected an array of schema paths or a hash with a 'schemas' key."
|
129
|
-
return
|
130
|
-
end
|
110
|
+
# Load schema manifest
|
111
|
+
manifest = Expressir::SchemaManifest.from_file(path)
|
112
|
+
schema_files = manifest.schemas.map(&:path)
|
113
|
+
|
114
|
+
say "Found #{schema_files.size} schema files to process"
|
131
115
|
|
132
116
|
# Initialize progress bar
|
133
117
|
if schema_files && !schema_files.empty?
|
@@ -150,12 +134,15 @@ module Expressir
|
|
150
134
|
|
151
135
|
# Create and add the report
|
152
136
|
skip_types = parse_skip_types
|
153
|
-
report = Expressir::Coverage::Report.from_repository(
|
137
|
+
report = Expressir::Coverage::Report.from_repository(
|
138
|
+
repository,
|
139
|
+
skip_types,
|
140
|
+
ignored_files,
|
141
|
+
)
|
154
142
|
reports << report
|
155
143
|
end
|
156
144
|
rescue StandardError => e
|
157
|
-
say "Error processing
|
158
|
-
say "Debug: schema_list structure: #{schema_list.class}" if schema_list
|
145
|
+
say "Error processing schema manifest #{path}: #{e.message}"
|
159
146
|
end
|
160
147
|
end
|
161
148
|
|
@@ -200,7 +187,8 @@ module Expressir
|
|
200
187
|
# Add rows
|
201
188
|
dirs.each do |dir, stats|
|
202
189
|
coverage = stats["total"].positive? ? (stats["documented"].to_f / stats["total"] * 100).round(2) : 100.0
|
203
|
-
table.add_row [dir, stats["total"], stats["documented"],
|
190
|
+
table.add_row [dir, stats["total"], stats["documented"],
|
191
|
+
"#{coverage}%"]
|
204
192
|
end
|
205
193
|
|
206
194
|
say table
|
@@ -250,10 +238,12 @@ module Expressir
|
|
250
238
|
},
|
251
239
|
)
|
252
240
|
|
253
|
-
table.add_row ["Coverage Percentage",
|
241
|
+
table.add_row ["Coverage Percentage",
|
242
|
+
"#{overall['coverage_percentage']}%"]
|
254
243
|
table.add_row ["Total Entities", overall["total_entities"]]
|
255
244
|
table.add_row ["Documented Entities", overall["documented_entities"]]
|
256
|
-
table.add_row ["Undocumented Entities",
|
245
|
+
table.add_row ["Undocumented Entities",
|
246
|
+
overall["undocumented_entities"]]
|
257
247
|
|
258
248
|
say table
|
259
249
|
end
|
@@ -265,10 +255,20 @@ module Expressir
|
|
265
255
|
|
266
256
|
overall_stats = {
|
267
257
|
"total_entities" => reports.sum { |r| r.total_entities.size },
|
268
|
-
"documented_entities" => reports.sum
|
269
|
-
|
270
|
-
|
271
|
-
|
258
|
+
"documented_entities" => reports.sum do |r|
|
259
|
+
r.documented_entities.size
|
260
|
+
end,
|
261
|
+
"undocumented_entities" => reports.sum do |r|
|
262
|
+
r.undocumented_entities.size
|
263
|
+
end,
|
264
|
+
"coverage_percentage" => if reports.sum do |r|
|
265
|
+
r.total_entities.size
|
266
|
+
end.positive?
|
267
|
+
(reports.sum do |r|
|
268
|
+
r.documented_entities.size
|
269
|
+
end.to_f / reports.sum do |r|
|
270
|
+
r.total_entities.size
|
271
|
+
end * 100).round(2)
|
272
272
|
else
|
273
273
|
100.0
|
274
274
|
end,
|
@@ -296,7 +296,8 @@ module Expressir
|
|
296
296
|
|
297
297
|
def display_json_output(reports)
|
298
298
|
output_file = options[:output] || "coverage_report.json"
|
299
|
-
File.write(output_file,
|
299
|
+
File.write(output_file,
|
300
|
+
JSON.pretty_generate(build_structured_report(reports)))
|
300
301
|
say "JSON coverage report written to: #{output_file}"
|
301
302
|
end
|
302
303
|
|
data/lib/expressir/coverage.rb
CHANGED
@@ -236,7 +236,9 @@ module Expressir
|
|
236
236
|
# @return [Hash] A hash with coverage information
|
237
237
|
def process_schema(schema)
|
238
238
|
entities = Expressir::Coverage.find_entities(schema, @skip_types)
|
239
|
-
documented = entities.select
|
239
|
+
documented = entities.select do |e|
|
240
|
+
Expressir::Coverage.entity_documented?(e)
|
241
|
+
end
|
240
242
|
undocumented = entities - documented
|
241
243
|
|
242
244
|
coverage = entities.empty? ? 100.0 : (documented.size.to_f / entities.size) * 100
|
@@ -400,10 +402,18 @@ module Expressir
|
|
400
402
|
entities.concat(container.subtype_constraints) if container.subtype_constraints
|
401
403
|
|
402
404
|
# Recursively find nested entities in nested containers
|
403
|
-
container.types&.each
|
404
|
-
|
405
|
-
|
406
|
-
container.
|
405
|
+
container.types&.each do |type|
|
406
|
+
entities.concat(find_nested_entities(type))
|
407
|
+
end
|
408
|
+
container.entities&.each do |entity|
|
409
|
+
entities.concat(find_nested_entities(entity))
|
410
|
+
end
|
411
|
+
container.functions&.each do |function|
|
412
|
+
entities.concat(find_nested_entities(function))
|
413
|
+
end
|
414
|
+
container.procedures&.each do |procedure|
|
415
|
+
entities.concat(find_nested_entities(procedure))
|
416
|
+
end
|
407
417
|
|
408
418
|
when Expressir::Model::Declarations::Rule
|
409
419
|
# Rule nested entities
|
@@ -416,10 +426,18 @@ module Expressir
|
|
416
426
|
entities.concat(container.subtype_constraints) if container.subtype_constraints
|
417
427
|
|
418
428
|
# Recursively find nested entities in nested containers
|
419
|
-
container.types&.each
|
420
|
-
|
421
|
-
|
422
|
-
container.
|
429
|
+
container.types&.each do |type|
|
430
|
+
entities.concat(find_nested_entities(type))
|
431
|
+
end
|
432
|
+
container.entities&.each do |entity|
|
433
|
+
entities.concat(find_nested_entities(entity))
|
434
|
+
end
|
435
|
+
container.functions&.each do |function|
|
436
|
+
entities.concat(find_nested_entities(function))
|
437
|
+
end
|
438
|
+
container.procedures&.each do |procedure|
|
439
|
+
entities.concat(find_nested_entities(procedure))
|
440
|
+
end
|
423
441
|
|
424
442
|
when Expressir::Model::Declarations::Procedure
|
425
443
|
# Procedure nested entities
|
@@ -433,10 +451,18 @@ module Expressir
|
|
433
451
|
entities.concat(container.subtype_constraints) if container.subtype_constraints
|
434
452
|
|
435
453
|
# Recursively find nested entities in nested containers
|
436
|
-
container.types&.each
|
437
|
-
|
438
|
-
|
439
|
-
container.
|
454
|
+
container.types&.each do |type|
|
455
|
+
entities.concat(find_nested_entities(type))
|
456
|
+
end
|
457
|
+
container.entities&.each do |entity|
|
458
|
+
entities.concat(find_nested_entities(entity))
|
459
|
+
end
|
460
|
+
container.functions&.each do |function|
|
461
|
+
entities.concat(find_nested_entities(function))
|
462
|
+
end
|
463
|
+
container.procedures&.each do |procedure|
|
464
|
+
entities.concat(find_nested_entities(procedure))
|
465
|
+
end
|
440
466
|
|
441
467
|
when Expressir::Model::Declarations::Interface
|
442
468
|
# Interface nested entities
|
@@ -498,7 +524,7 @@ module Expressir
|
|
498
524
|
type_subtype_skips.include?(entity_subtype)
|
499
525
|
# Check FUNCTION:INNER exclusions
|
500
526
|
elsif entity_class == "Expressir::Model::Declarations::Function" && function_subtype_skips.include?("INNER")
|
501
|
-
|
527
|
+
inner_function?(entity)
|
502
528
|
else
|
503
529
|
false
|
504
530
|
end
|
@@ -528,7 +554,7 @@ module Expressir
|
|
528
554
|
# Check if a function is an inner function (nested within another function, rule, or procedure)
|
529
555
|
# @param function_entity [Expressir::Model::Declarations::Function] The function entity to check
|
530
556
|
# @return [Boolean] True if the function is nested within another function, rule, or procedure
|
531
|
-
def self.
|
557
|
+
def self.inner_function?(function_entity)
|
532
558
|
return false unless function_entity.respond_to?(:parent) && function_entity.parent
|
533
559
|
|
534
560
|
# Check if the parent is a function, rule, or procedure (not a schema)
|
@@ -9,7 +9,8 @@ module Expressir
|
|
9
9
|
# @param root_path [String] Express repository root path, to be stripped from Express file paths to create a portable cache file
|
10
10
|
# @param test_overwrite_version [String] don't use, only for tests
|
11
11
|
# @return [nil]
|
12
|
-
def self.to_file(file, content, root_path: nil,
|
12
|
+
def self.to_file(file, content, root_path: nil,
|
13
|
+
test_overwrite_version: nil)
|
13
14
|
version = test_overwrite_version || VERSION
|
14
15
|
|
15
16
|
cache = Model::Cache.new(
|
@@ -91,6 +91,8 @@ module Expressir
|
|
91
91
|
format_declarations_variable(node)
|
92
92
|
when Model::Declarations::WhereRule
|
93
93
|
format_declarations_where_rule(node)
|
94
|
+
when Model::Declarations::InformalPropositionRule
|
95
|
+
format_declarations_informal_proposition_rule(node)
|
94
96
|
when Model::DataTypes::Aggregate
|
95
97
|
format_data_types_aggregate(node)
|
96
98
|
when Model::DataTypes::Array
|
@@ -283,9 +285,15 @@ module Expressir
|
|
283
285
|
derived_attributes = []
|
284
286
|
inverse_attributes = []
|
285
287
|
else
|
286
|
-
explicit_attributes = node.attributes.select
|
287
|
-
|
288
|
-
|
288
|
+
explicit_attributes = node.attributes.select do |x|
|
289
|
+
x.kind == Model::Declarations::Attribute::EXPLICIT
|
290
|
+
end
|
291
|
+
derived_attributes = node.attributes.select do |x|
|
292
|
+
x.kind == Model::Declarations::Attribute::DERIVED
|
293
|
+
end
|
294
|
+
inverse_attributes = node.attributes.select do |x|
|
295
|
+
x.kind == Model::Declarations::Attribute::INVERSE
|
296
|
+
end
|
289
297
|
end
|
290
298
|
|
291
299
|
[
|
@@ -393,7 +401,9 @@ module Expressir
|
|
393
401
|
parameter_indent = INDENT_CHAR * "FUNCTION #{node.id}(".length
|
394
402
|
[
|
395
403
|
"(",
|
396
|
-
node.parameters.map
|
404
|
+
node.parameters.map do |x|
|
405
|
+
format(x)
|
406
|
+
end.join(";\n#{parameter_indent}"),
|
397
407
|
")",
|
398
408
|
].join
|
399
409
|
end,
|
@@ -513,7 +523,9 @@ module Expressir
|
|
513
523
|
parameter_indent = INDENT_CHAR * "PROCEDURE #{node.id}(".length
|
514
524
|
[
|
515
525
|
"(",
|
516
|
-
node.parameters.map
|
526
|
+
node.parameters.map do |x|
|
527
|
+
format(x)
|
528
|
+
end.join(";\n#{parameter_indent}"),
|
517
529
|
")",
|
518
530
|
].join
|
519
531
|
end,
|
@@ -825,6 +837,18 @@ module Expressir
|
|
825
837
|
].join
|
826
838
|
end
|
827
839
|
|
840
|
+
def format_declarations_informal_proposition_rule(node)
|
841
|
+
[
|
842
|
+
*if node.id
|
843
|
+
[
|
844
|
+
node.id,
|
845
|
+
":",
|
846
|
+
" ",
|
847
|
+
].join
|
848
|
+
end,
|
849
|
+
].join
|
850
|
+
end
|
851
|
+
|
828
852
|
def format_expressions_aggregate_initializer(node)
|
829
853
|
node.items ||= []
|
830
854
|
[
|
@@ -912,7 +936,7 @@ module Expressir
|
|
912
936
|
]
|
913
937
|
end
|
914
938
|
|
915
|
-
[format(node.function), params].
|
939
|
+
[format(node.function), params].join
|
916
940
|
end
|
917
941
|
|
918
942
|
def format_expressions_interval(node)
|
@@ -950,7 +974,9 @@ module Expressir
|
|
950
974
|
"|",
|
951
975
|
" ",
|
952
976
|
format(node.expression),
|
953
|
-
*format_remarks(node).instance_eval
|
977
|
+
*format_remarks(node).instance_eval do |x|
|
978
|
+
x&.length&.positive? ? ["\n", *x, "\n"] : x
|
979
|
+
end,
|
954
980
|
")",
|
955
981
|
].join
|
956
982
|
end
|
@@ -1409,7 +1435,9 @@ module Expressir
|
|
1409
1435
|
"\n",
|
1410
1436
|
indent([
|
1411
1437
|
"(",
|
1412
|
-
node.items.map
|
1438
|
+
node.items.map do |x|
|
1439
|
+
format(x)
|
1440
|
+
end.join(",\n#{item_indent}"),
|
1413
1441
|
")",
|
1414
1442
|
].join),
|
1415
1443
|
].join
|
@@ -1425,7 +1453,9 @@ module Expressir
|
|
1425
1453
|
"\n",
|
1426
1454
|
indent([
|
1427
1455
|
"(",
|
1428
|
-
node.items.map
|
1456
|
+
node.items.map do |x|
|
1457
|
+
format(x)
|
1458
|
+
end.join(",\n#{item_indent}"),
|
1429
1459
|
")",
|
1430
1460
|
].join),
|
1431
1461
|
].join
|
@@ -1545,7 +1575,9 @@ module Expressir
|
|
1545
1575
|
"\n",
|
1546
1576
|
indent([
|
1547
1577
|
"(",
|
1548
|
-
node.items.map
|
1578
|
+
node.items.map do |x|
|
1579
|
+
format(x)
|
1580
|
+
end.join(",\n#{item_indent}"),
|
1549
1581
|
")",
|
1550
1582
|
].join),
|
1551
1583
|
].join
|
@@ -1559,7 +1591,9 @@ module Expressir
|
|
1559
1591
|
"\n",
|
1560
1592
|
indent([
|
1561
1593
|
"(",
|
1562
|
-
node.items.map
|
1594
|
+
node.items.map do |x|
|
1595
|
+
format(x)
|
1596
|
+
end.join(",\n#{item_indent}"),
|
1563
1597
|
")",
|
1564
1598
|
].join),
|
1565
1599
|
].join
|
@@ -1627,6 +1661,14 @@ module Expressir
|
|
1627
1661
|
remark,
|
1628
1662
|
"*)",
|
1629
1663
|
].join("\n")
|
1664
|
+
elsif node.path.nil? && node.id.include?("IP")
|
1665
|
+
# Handle inmediate informal propositions
|
1666
|
+
[
|
1667
|
+
"--",
|
1668
|
+
node.id,
|
1669
|
+
" ",
|
1670
|
+
remark,
|
1671
|
+
].join
|
1630
1672
|
else
|
1631
1673
|
# Handle tail remarks
|
1632
1674
|
[
|
@@ -1661,7 +1703,7 @@ module Expressir
|
|
1661
1703
|
# Add tagged remarks
|
1662
1704
|
if node.class.method_defined?(:remarks) && !@no_remarks &&
|
1663
1705
|
!node.remarks.nil?
|
1664
|
-
remarks.concat(node.remarks.map do |remark|
|
1706
|
+
remarks.concat(node.remarks.compact.map do |remark|
|
1665
1707
|
format_remark(node, remark)
|
1666
1708
|
end)
|
1667
1709
|
end
|
@@ -9,7 +9,8 @@ module Expressir
|
|
9
9
|
# @!visibility private
|
10
10
|
def self.included(mod)
|
11
11
|
if !mod.superclass.private_method_defined? :format_references_simple_reference
|
12
|
-
raise Error::FormatterMethodMissingError.new("HyperlinkFormatter",
|
12
|
+
raise Error::FormatterMethodMissingError.new("HyperlinkFormatter",
|
13
|
+
"format_references_simple_reference")
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|