expressir 2.1.21 → 2.1.22
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 -23
- data/README.adoc +162 -2
- data/lib/expressir/cli.rb +1 -0
- data/lib/expressir/commands/coverage.rb +91 -22
- data/lib/expressir/coverage.rb +59 -11
- data/lib/expressir/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fab262d4a8c290f1dc292ff8ea22e9f631356945fb76bed736594dad060078b0
|
4
|
+
data.tar.gz: 45e33a9920262038833f1f00113b12527eb9dc64a71d29d8e0b5f36bd89842ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bbc6a59dc02947a9c2ed5971900094ce183a4bbe0bdc4e3e762906d8d0675bc5c3ed145c37f17a406c406db783d4dcac1055938cdef2f54382bf1647bd57a61
|
7
|
+
data.tar.gz: ae2c40bc87334138a4ce2cbfdc04bf699da520f62483bf9a8760117ba00b7d45dde639e0c292b5cdb8a285c1d01bd59aef4f5bf70f976ded713c1d7fb4ec5a61
|
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-07
|
3
|
+
# on 2025-06-07 07:39:56 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
|
@@ -13,6 +13,24 @@ Gemspec/RequiredRubyVersion:
|
|
13
13
|
Exclude:
|
14
14
|
- 'expressir.gemspec'
|
15
15
|
|
16
|
+
# Offense count: 2
|
17
|
+
# This cop supports safe autocorrection (--autocorrect).
|
18
|
+
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
19
|
+
# SupportedStyles: special_inside_parentheses, consistent, align_braces
|
20
|
+
Layout/FirstHashElementIndentation:
|
21
|
+
Exclude:
|
22
|
+
- 'spec/expressir/commands/coverage_ignore_files_spec.rb'
|
23
|
+
|
24
|
+
# Offense count: 1
|
25
|
+
# This cop supports safe autocorrection (--autocorrect).
|
26
|
+
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
27
|
+
# SupportedHashRocketStyles: key, separator, table
|
28
|
+
# SupportedColonStyles: key, separator, table
|
29
|
+
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
30
|
+
Layout/HashAlignment:
|
31
|
+
Exclude:
|
32
|
+
- 'spec/expressir/commands/coverage_ignore_files_spec.rb'
|
33
|
+
|
16
34
|
# Offense count: 2
|
17
35
|
# This cop supports safe autocorrection (--autocorrect).
|
18
36
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
@@ -27,25 +45,11 @@ Lint/DuplicateBranch:
|
|
27
45
|
Exclude:
|
28
46
|
- 'lib/expressir/coverage.rb'
|
29
47
|
|
30
|
-
# Offense count: 1
|
31
|
-
# This cop supports safe autocorrection (--autocorrect).
|
32
|
-
Lint/ScriptPermission:
|
33
|
-
Exclude:
|
34
|
-
- 'update_yaml_fixtures.rb'
|
35
|
-
|
36
48
|
# Offense count: 3
|
37
49
|
Lint/ShadowingOuterLocalVariable:
|
38
50
|
Exclude:
|
39
51
|
- 'lib/expressir/express/visitor.rb'
|
40
52
|
|
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
|
-
|
49
53
|
# Offense count: 2
|
50
54
|
# This cop supports safe autocorrection (--autocorrect).
|
51
55
|
# Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
|
@@ -55,7 +59,7 @@ Lint/UnusedMethodArgument:
|
|
55
59
|
- 'lib/expressir/express/cache.rb'
|
56
60
|
- 'lib/expressir/express/parser.rb'
|
57
61
|
|
58
|
-
# Offense count:
|
62
|
+
# Offense count: 79
|
59
63
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
60
64
|
Metrics/AbcSize:
|
61
65
|
Exclude:
|
@@ -80,7 +84,7 @@ Metrics/AbcSize:
|
|
80
84
|
Metrics/BlockLength:
|
81
85
|
Max: 143
|
82
86
|
|
83
|
-
# Offense count:
|
87
|
+
# Offense count: 57
|
84
88
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
85
89
|
Metrics/CyclomaticComplexity:
|
86
90
|
Exclude:
|
@@ -95,12 +99,12 @@ Metrics/CyclomaticComplexity:
|
|
95
99
|
- 'lib/expressir/model/model_element.rb'
|
96
100
|
- 'spec/support/model_element_helper.rb'
|
97
101
|
|
98
|
-
# Offense count:
|
102
|
+
# Offense count: 103
|
99
103
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
100
104
|
Metrics/MethodLength:
|
101
105
|
Max: 82
|
102
106
|
|
103
|
-
# Offense count:
|
107
|
+
# Offense count: 45
|
104
108
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
105
109
|
Metrics/PerceivedComplexity:
|
106
110
|
Exclude:
|
@@ -133,8 +137,18 @@ Style/MissingRespondToMissing:
|
|
133
137
|
Exclude:
|
134
138
|
- 'lib/expressir/express/visitor.rb'
|
135
139
|
|
136
|
-
# Offense count:
|
137
|
-
# This cop supports
|
138
|
-
|
140
|
+
# Offense count: 1
|
141
|
+
# This cop supports safe autocorrection (--autocorrect).
|
142
|
+
# Configuration parameters: EnforcedStyleForMultiline.
|
143
|
+
# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
|
144
|
+
Style/TrailingCommaInArrayLiteral:
|
139
145
|
Exclude:
|
140
|
-
- '
|
146
|
+
- 'spec/expressir/commands/coverage_ignore_files_spec.rb'
|
147
|
+
|
148
|
+
# Offense count: 1
|
149
|
+
# This cop supports safe autocorrection (--autocorrect).
|
150
|
+
# Configuration parameters: EnforcedStyleForMultiline.
|
151
|
+
# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
|
152
|
+
Style/TrailingCommaInHashLiteral:
|
153
|
+
Exclude:
|
154
|
+
- 'spec/expressir/commands/coverage_ignore_files_spec.rb'
|
data/README.adoc
CHANGED
@@ -271,6 +271,7 @@ The coverage command supports different output formats and exclusion options:
|
|
271
271
|
| `--format json` | Output in JSON format for programmatic processing
|
272
272
|
| `--format yaml` | Output in YAML format for programmatic processing
|
273
273
|
| `--exclude TYPES` | Comma-separated list of EXPRESS entity types to exclude from coverage analysis
|
274
|
+
| `--ignore-files PATH` | Path to YAML file containing array of files to ignore from overall coverage calculation
|
274
275
|
|===
|
275
276
|
|
276
277
|
==== Excluding entity types from coverage
|
@@ -360,11 +361,12 @@ expressir coverage --exclude=TYPE:SELECT,FUNCTION:INNER schemas/resources/action
|
|
360
361
|
|
361
362
|
This is useful when you want to focus documentation coverage on top-level
|
362
363
|
functions while excluding nested helper functions that may not require
|
363
|
-
individual documentation.
|
364
|
+
individual documentation. The exclusion works recursively, excluding functions
|
365
|
+
at any nesting level within other constructs.
|
364
366
|
|
365
367
|
Valid FUNCTION subtypes that can be excluded:
|
366
368
|
|
367
|
-
`INNER`:: Inner functions nested within other functions, rules, or procedures
|
369
|
+
`INNER`:: Inner functions nested within other functions, rules, or procedures (at any depth)
|
368
370
|
+
|
369
371
|
[example]
|
370
372
|
====
|
@@ -372,14 +374,172 @@ Valid FUNCTION subtypes that can be excluded:
|
|
372
374
|
FUNCTION outer_function : BOOLEAN;
|
373
375
|
-- This inner function would be excluded with FUNCTION:INNER
|
374
376
|
FUNCTION inner_helper_function : BOOLEAN;
|
377
|
+
-- Even deeply nested functions are excluded
|
378
|
+
FUNCTION deeply_nested_function : BOOLEAN;
|
379
|
+
RETURN (TRUE);
|
380
|
+
END_FUNCTION;
|
375
381
|
RETURN (TRUE);
|
376
382
|
END_FUNCTION;
|
377
383
|
|
378
384
|
RETURN (TRUE);
|
379
385
|
END_FUNCTION;
|
386
|
+
|
387
|
+
RULE example_rule FOR (some_entity);
|
388
|
+
-- Inner functions in rules are also excluded
|
389
|
+
FUNCTION inner_function_in_rule : BOOLEAN;
|
390
|
+
RETURN (TRUE);
|
391
|
+
END_FUNCTION;
|
392
|
+
WHERE
|
393
|
+
WR1: inner_function_in_rule();
|
394
|
+
END_RULE;
|
395
|
+
|
396
|
+
PROCEDURE example_procedure;
|
397
|
+
-- Inner functions in procedures are also excluded
|
398
|
+
FUNCTION inner_function_in_procedure : BOOLEAN;
|
399
|
+
RETURN (TRUE);
|
400
|
+
END_FUNCTION;
|
401
|
+
END_PROCEDURE;
|
380
402
|
----
|
381
403
|
====
|
382
404
|
|
405
|
+
The `FUNCTION:INNER` exclusion helps maintain focus on documenting the primary
|
406
|
+
API functions while ignoring implementation details of nested helper functions.
|
407
|
+
|
408
|
+
==== Ignoring files from coverage calculation
|
409
|
+
|
410
|
+
You can exclude entire files from the overall coverage calculation using the
|
411
|
+
`--ignore-files` option. This is useful when you have files that should not
|
412
|
+
contribute to the overall documentation coverage statistics, such as test
|
413
|
+
schemas, example files, or legacy schemas.
|
414
|
+
|
415
|
+
[source, sh]
|
416
|
+
----
|
417
|
+
# Use ignore files to exclude specific files from coverage calculation
|
418
|
+
expressir coverage --ignore-files ignore_list.yaml schemas/resources/
|
419
|
+
|
420
|
+
# Combine with other options
|
421
|
+
expressir coverage --ignore-files ignore_list.yaml --exclude=TYPE:SELECT --format=json schemas/resources/
|
422
|
+
----
|
423
|
+
|
424
|
+
===== Ignore files YAML format
|
425
|
+
|
426
|
+
The ignore files YAML should contain an array of file patterns. Each pattern
|
427
|
+
can be either an exact file path or use glob patterns for matching multiple files.
|
428
|
+
|
429
|
+
.ignore_list.yaml
|
430
|
+
[source, yaml]
|
431
|
+
----
|
432
|
+
# Array of file patterns to ignore
|
433
|
+
- examples/test_schema.exp # Exact file path
|
434
|
+
- examples/*_test_*.exp # Glob pattern for test files
|
435
|
+
- legacy/old_*.exp # Glob pattern for legacy files
|
436
|
+
- temp/temporary_schema.exp # Another exact path
|
437
|
+
----
|
438
|
+
|
439
|
+
===== Pattern matching behavior
|
440
|
+
|
441
|
+
File patterns in the ignore files YAML support:
|
442
|
+
|
443
|
+
* **Exact paths**: Match specific files exactly
|
444
|
+
* **Glob patterns**: Use `*` for wildcard matching
|
445
|
+
* **Relative paths**: Patterns are resolved relative to the YAML file's directory
|
446
|
+
* **Absolute paths**: Full system paths are also supported
|
447
|
+
|
448
|
+
[source, yaml]
|
449
|
+
----
|
450
|
+
# Examples of different pattern types
|
451
|
+
- schemas/action_schema/action_schema.exp # Exact relative path
|
452
|
+
- /full/path/to/schema.exp # Absolute path
|
453
|
+
- schemas/**/test_*.exp # Recursive glob pattern
|
454
|
+
- temp/*.exp # All .exp files in temp directory
|
455
|
+
----
|
456
|
+
|
457
|
+
===== Behavior of ignored files
|
458
|
+
|
459
|
+
When files are ignored using the `--ignore-files` option:
|
460
|
+
|
461
|
+
. **Excluded from overall statistics**: Ignored files do not contribute to the
|
462
|
+
overall coverage percentage calculation
|
463
|
+
|
464
|
+
. **Still processed and reported**: Ignored files are still analyzed and appear
|
465
|
+
in the output, but marked with an `ignored: true` flag
|
466
|
+
|
467
|
+
. **Separate reporting section**: In JSON/YAML output formats, ignored files
|
468
|
+
appear in both the main `files` section (with the ignored flag) and in a
|
469
|
+
separate `ignored_files` section
|
470
|
+
|
471
|
+
. **Overall statistics updated**: The overall statistics include additional
|
472
|
+
fields showing the count of ignored files and entities
|
473
|
+
|
474
|
+
.Example JSON output with ignored files:
|
475
|
+
[source, json]
|
476
|
+
----
|
477
|
+
{
|
478
|
+
"overall": {
|
479
|
+
"coverage_percentage": 75.0,
|
480
|
+
"total_entities": 100,
|
481
|
+
"documented_entities": 75,
|
482
|
+
"undocumented_entities": 25,
|
483
|
+
"ignored_files_count": 2,
|
484
|
+
"ignored_entities_count": 15
|
485
|
+
},
|
486
|
+
"files": [
|
487
|
+
{
|
488
|
+
"file": "schemas/main_schema.exp",
|
489
|
+
"ignored": false,
|
490
|
+
"coverage": 80.0,
|
491
|
+
"total": 50,
|
492
|
+
"documented": 40,
|
493
|
+
"undocumented": ["entity1", "entity2"]
|
494
|
+
},
|
495
|
+
{
|
496
|
+
"file": "examples/test_schema.exp",
|
497
|
+
"ignored": true,
|
498
|
+
"matched_pattern": "examples/*_test_*.exp",
|
499
|
+
"coverage": 20.0,
|
500
|
+
"total": 10,
|
501
|
+
"documented": 2,
|
502
|
+
"undocumented": ["test_entity1", "test_entity2"]
|
503
|
+
}
|
504
|
+
],
|
505
|
+
"ignored_files": [
|
506
|
+
{
|
507
|
+
"file": "examples/test_schema.exp",
|
508
|
+
"matched_pattern": "examples/*_test_*.exp",
|
509
|
+
"coverage": 20.0,
|
510
|
+
"total": 10,
|
511
|
+
"documented": 2,
|
512
|
+
"undocumented": ["test_entity1", "test_entity2"]
|
513
|
+
}
|
514
|
+
]
|
515
|
+
}
|
516
|
+
----
|
517
|
+
|
518
|
+
===== Error handling
|
519
|
+
|
520
|
+
The ignore files functionality handles various error conditions gracefully:
|
521
|
+
|
522
|
+
* **Missing YAML file**: If the specified ignore files YAML doesn't exist, a
|
523
|
+
warning is displayed and coverage analysis continues normally
|
524
|
+
|
525
|
+
* **Invalid YAML format**: If the YAML file is malformed or doesn't contain an
|
526
|
+
array, a warning is displayed and the file is ignored
|
527
|
+
|
528
|
+
* **Non-matching patterns**: Patterns that don't match any files are silently
|
529
|
+
ignored (no error or warning)
|
530
|
+
|
531
|
+
* **Permission errors**: File access errors are reported as warnings
|
532
|
+
|
533
|
+
===== Use cases for ignore files
|
534
|
+
|
535
|
+
Common scenarios where ignore files are useful:
|
536
|
+
|
537
|
+
* **Test schemas**: Exclude test or example schemas from production coverage metrics
|
538
|
+
* **Legacy files**: Ignore old schemas that are being phased out
|
539
|
+
* **Generated files**: Exclude automatically generated schemas
|
540
|
+
* **Work-in-progress**: Temporarily ignore files under development
|
541
|
+
* **Different coverage standards**: Apply different documentation standards to different file sets
|
542
|
+
|
383
543
|
Valid TYPE subtypes that can be excluded:
|
384
544
|
|
385
545
|
`AGGREGATE`:: Aggregate type
|
data/lib/expressir/cli.rb
CHANGED
@@ -57,6 +57,7 @@ module Expressir
|
|
57
57
|
method_option :format, type: :string, desc: "Output format (text, json, yaml)", default: "text"
|
58
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
59
|
method_option :output, type: :string, desc: "Output file path for JSON/YAML formats (defaults to coverage_report.json/yaml)"
|
60
|
+
method_option :ignore_files, type: :string, desc: "Path to YAML file containing array of files to ignore from overall coverage calculation"
|
60
61
|
def coverage(*paths)
|
61
62
|
Commands::Coverage.new(options).run(paths)
|
62
63
|
end
|
@@ -32,27 +32,28 @@ module Expressir
|
|
32
32
|
|
33
33
|
def collect_reports(paths)
|
34
34
|
reports = []
|
35
|
+
ignored_files = parse_ignore_files
|
35
36
|
|
36
37
|
paths.each do |path|
|
37
|
-
handle_path(path, reports)
|
38
|
+
handle_path(path, reports, ignored_files)
|
38
39
|
end
|
39
40
|
|
40
41
|
reports
|
41
42
|
end
|
42
43
|
|
43
|
-
def handle_path(path, reports)
|
44
|
+
def handle_path(path, reports, ignored_files)
|
44
45
|
if File.directory?(path)
|
45
|
-
handle_directory(path, reports)
|
46
|
+
handle_directory(path, reports, ignored_files)
|
46
47
|
elsif File.extname(path).downcase == ".exp"
|
47
|
-
handle_express_file(path, reports)
|
48
|
+
handle_express_file(path, reports, ignored_files)
|
48
49
|
elsif [".yml", ".yaml"].include?(File.extname(path).downcase)
|
49
|
-
handle_yaml_manifest(path, reports)
|
50
|
+
handle_yaml_manifest(path, reports, ignored_files)
|
50
51
|
else
|
51
52
|
say "Unsupported file type: #{path}"
|
52
53
|
end
|
53
54
|
end
|
54
55
|
|
55
|
-
def handle_directory(path, reports)
|
56
|
+
def handle_directory(path, reports, ignored_files)
|
56
57
|
say "Processing directory: #{path}"
|
57
58
|
exp_files = Dir.glob(File.join(path, "**", "*.exp"))
|
58
59
|
if exp_files.empty?
|
@@ -79,26 +80,26 @@ module Expressir
|
|
79
80
|
progress.increment
|
80
81
|
end
|
81
82
|
skip_types = parse_skip_types
|
82
|
-
report = Expressir::Coverage::Report.from_repository(repository, skip_types)
|
83
|
+
report = Expressir::Coverage::Report.from_repository(repository, skip_types, ignored_files)
|
83
84
|
reports << report
|
84
85
|
rescue StandardError => e
|
85
86
|
say "Error processing directory #{path}: #{e.message}"
|
86
87
|
end
|
87
88
|
end
|
88
89
|
|
89
|
-
def handle_express_file(path, reports)
|
90
|
+
def handle_express_file(path, reports, ignored_files)
|
90
91
|
say "Processing file: #{path}"
|
91
92
|
begin
|
92
93
|
# For a single file, we don't need a progress bar
|
93
94
|
skip_types = parse_skip_types
|
94
|
-
report = Expressir::Coverage::Report.from_file(path, skip_types)
|
95
|
+
report = Expressir::Coverage::Report.from_file(path, skip_types, ignored_files)
|
95
96
|
reports << report
|
96
97
|
rescue StandardError => e
|
97
98
|
say "Error processing file #{path}: #{e.message}"
|
98
99
|
end
|
99
100
|
end
|
100
101
|
|
101
|
-
def handle_yaml_manifest(path, reports)
|
102
|
+
def handle_yaml_manifest(path, reports, ignored_files)
|
102
103
|
say "Processing YAML manifest: #{path}"
|
103
104
|
begin
|
104
105
|
schema_list = YAML.load_file(path)
|
@@ -149,7 +150,7 @@ module Expressir
|
|
149
150
|
|
150
151
|
# Create and add the report
|
151
152
|
skip_types = parse_skip_types
|
152
|
-
report = Expressir::Coverage::Report.from_repository(repository, skip_types)
|
153
|
+
report = Expressir::Coverage::Report.from_repository(repository, skip_types, ignored_files)
|
153
154
|
reports << report
|
154
155
|
end
|
155
156
|
rescue StandardError => e
|
@@ -258,20 +259,39 @@ module Expressir
|
|
258
259
|
end
|
259
260
|
|
260
261
|
def build_structured_report(reports)
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
262
|
+
# Calculate ignored file statistics
|
263
|
+
ignored_files = reports.flat_map(&:ignored_file_reports)
|
264
|
+
ignored_entities_count = ignored_files.sum { |f| f["total"] }
|
265
|
+
|
266
|
+
overall_stats = {
|
267
|
+
"total_entities" => reports.sum { |r| r.total_entities.size },
|
268
|
+
"documented_entities" => reports.sum { |r| r.documented_entities.size },
|
269
|
+
"undocumented_entities" => reports.sum { |r| r.undocumented_entities.size },
|
270
|
+
"coverage_percentage" => if reports.sum { |r| r.total_entities.size }.positive?
|
271
|
+
(reports.sum { |r| r.documented_entities.size }.to_f / reports.sum { |r| r.total_entities.size } * 100).round(2)
|
272
|
+
else
|
273
|
+
100.0
|
274
|
+
end,
|
275
|
+
}
|
276
|
+
|
277
|
+
# Add ignored file information if there are any
|
278
|
+
if ignored_files.any?
|
279
|
+
overall_stats["ignored_files_count"] = ignored_files.size
|
280
|
+
overall_stats["ignored_entities_count"] = ignored_entities_count
|
281
|
+
end
|
282
|
+
|
283
|
+
structured_report = {
|
284
|
+
"overall" => overall_stats,
|
272
285
|
"files" => reports.flat_map(&:file_reports),
|
273
286
|
"directories" => reports.flat_map(&:directory_reports),
|
274
287
|
}
|
288
|
+
|
289
|
+
# Add ignored files section if there are any
|
290
|
+
if ignored_files.any?
|
291
|
+
structured_report["ignored_files"] = ignored_files
|
292
|
+
end
|
293
|
+
|
294
|
+
structured_report
|
275
295
|
end
|
276
296
|
|
277
297
|
def display_json_output(reports)
|
@@ -343,6 +363,55 @@ module Expressir
|
|
343
363
|
end
|
344
364
|
end
|
345
365
|
end
|
366
|
+
|
367
|
+
# Parse and expand ignore files from YAML
|
368
|
+
# @return [Hash] Hash mapping absolute file paths to their matched patterns
|
369
|
+
def parse_ignore_files
|
370
|
+
ignore_files_option = options["ignore_files"] || options[:ignore_files]
|
371
|
+
return {} unless ignore_files_option
|
372
|
+
|
373
|
+
unless File.exist?(ignore_files_option)
|
374
|
+
say "Warning: Ignore files YAML not found: #{ignore_files_option}"
|
375
|
+
return {}
|
376
|
+
end
|
377
|
+
|
378
|
+
begin
|
379
|
+
patterns = YAML.load_file(ignore_files_option)
|
380
|
+
unless patterns.is_a?(Array)
|
381
|
+
say "Warning: Invalid ignore files YAML format. Expected an array of file patterns."
|
382
|
+
return {}
|
383
|
+
end
|
384
|
+
|
385
|
+
ignore_files_dir = File.dirname(File.expand_path(ignore_files_option))
|
386
|
+
expanded_files = {}
|
387
|
+
|
388
|
+
patterns.each do |pattern|
|
389
|
+
# Resolve pattern relative to the YAML file's directory
|
390
|
+
full_pattern = File.expand_path(pattern, ignore_files_dir)
|
391
|
+
|
392
|
+
# Expand glob pattern
|
393
|
+
matched_files = Dir.glob(full_pattern)
|
394
|
+
|
395
|
+
if matched_files.empty?
|
396
|
+
say "Warning: No files matched pattern: #{pattern}"
|
397
|
+
else
|
398
|
+
matched_files.each do |file_path|
|
399
|
+
# Store absolute path and the original pattern that matched it
|
400
|
+
expanded_files[File.expand_path(file_path)] = pattern
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
if expanded_files.any?
|
406
|
+
say "Found #{expanded_files.size} files to ignore from patterns"
|
407
|
+
end
|
408
|
+
|
409
|
+
expanded_files
|
410
|
+
rescue StandardError => e
|
411
|
+
say "Warning: Error processing ignore files YAML #{ignore_files_option}: #{e.message}"
|
412
|
+
{}
|
413
|
+
end
|
414
|
+
end
|
346
415
|
end
|
347
416
|
end
|
348
417
|
end
|
data/lib/expressir/coverage.rb
CHANGED
@@ -59,14 +59,16 @@ module Expressir
|
|
59
59
|
# Represents a documentation coverage report for EXPRESS schemas
|
60
60
|
class Report
|
61
61
|
attr_reader :repository, :schema_reports, :total_entities, :documented_entities,
|
62
|
-
:undocumented_entities
|
62
|
+
:undocumented_entities, :ignored_files
|
63
63
|
|
64
64
|
# Initialize a coverage report
|
65
65
|
# @param repository [Expressir::Model::Repository] The repository to analyze
|
66
66
|
# @param skip_types [Array<String>] Array of entity type names to skip from coverage
|
67
|
-
|
67
|
+
# @param ignored_files [Hash] Hash mapping absolute file paths to their matched patterns
|
68
|
+
def initialize(repository, skip_types = [], ignored_files = {})
|
68
69
|
@repository = repository
|
69
70
|
@skip_types = skip_types
|
71
|
+
@ignored_files = ignored_files
|
70
72
|
@schema_reports = []
|
71
73
|
@total_entities = []
|
72
74
|
@documented_entities = []
|
@@ -78,18 +80,20 @@ module Expressir
|
|
78
80
|
# Create a report from a repository
|
79
81
|
# @param repository [Expressir::Model::Repository] The repository to analyze
|
80
82
|
# @param skip_types [Array<String>] Array of entity type names to skip from coverage
|
83
|
+
# @param ignored_files [Hash] Hash mapping absolute file paths to their matched patterns
|
81
84
|
# @return [Report] The coverage report
|
82
|
-
def self.from_repository(repository, skip_types = [])
|
83
|
-
new(repository, skip_types)
|
85
|
+
def self.from_repository(repository, skip_types = [], ignored_files = {})
|
86
|
+
new(repository, skip_types, ignored_files)
|
84
87
|
end
|
85
88
|
|
86
89
|
# Create a report from a schema file
|
87
90
|
# @param path [String] Path to the schema file
|
88
91
|
# @param skip_types [Array<String>] Array of entity type names to skip from coverage
|
92
|
+
# @param ignored_files [Hash] Hash mapping absolute file paths to their matched patterns
|
89
93
|
# @return [Report] The coverage report
|
90
|
-
def self.from_file(path, skip_types = [])
|
94
|
+
def self.from_file(path, skip_types = [], ignored_files = {})
|
91
95
|
repository = Expressir::Express::Parser.from_file(path)
|
92
|
-
new(repository, skip_types)
|
96
|
+
new(repository, skip_types, ignored_files)
|
93
97
|
end
|
94
98
|
|
95
99
|
# Calculate the overall coverage percentage
|
@@ -113,6 +117,39 @@ module Expressir
|
|
113
117
|
absolute_path
|
114
118
|
end
|
115
119
|
|
120
|
+
file_report = {
|
121
|
+
"file" => relative_path,
|
122
|
+
"file_basename" => File.basename(absolute_path),
|
123
|
+
"directory" => File.dirname(absolute_path),
|
124
|
+
"total" => report[:total].size,
|
125
|
+
"documented" => report[:documented].size,
|
126
|
+
"undocumented" => report[:undocumented],
|
127
|
+
"coverage" => report[:coverage],
|
128
|
+
"ignored" => report[:ignored] || false,
|
129
|
+
}
|
130
|
+
|
131
|
+
# Add matched pattern for ignored files
|
132
|
+
if report[:ignored] && report[:matched_pattern]
|
133
|
+
file_report["matched_pattern"] = report[:matched_pattern]
|
134
|
+
end
|
135
|
+
|
136
|
+
file_report
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Get ignored file reports
|
141
|
+
# @return [Array<Hash>] Array of ignored file report hashes
|
142
|
+
def ignored_file_reports
|
143
|
+
@schema_reports.select { |report| report[:ignored] }.map do |report|
|
144
|
+
absolute_path = report[:schema].file
|
145
|
+
relative_path = begin
|
146
|
+
Pathname.new(absolute_path).relative_path_from(Pathname.pwd).to_s
|
147
|
+
rescue ArgumentError
|
148
|
+
# If paths are on different drives or otherwise incompatible,
|
149
|
+
# fall back to the absolute path
|
150
|
+
absolute_path
|
151
|
+
end
|
152
|
+
|
116
153
|
{
|
117
154
|
"file" => relative_path,
|
118
155
|
"file_basename" => File.basename(absolute_path),
|
@@ -121,6 +158,7 @@ module Expressir
|
|
121
158
|
"documented" => report[:documented].size,
|
122
159
|
"undocumented" => report[:undocumented],
|
123
160
|
"coverage" => report[:coverage],
|
161
|
+
"matched_pattern" => report[:matched_pattern],
|
124
162
|
}
|
125
163
|
end
|
126
164
|
end
|
@@ -182,11 +220,14 @@ module Expressir
|
|
182
220
|
schema_report = process_schema(schema)
|
183
221
|
@schema_reports << schema_report
|
184
222
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
223
|
+
# Only include non-ignored files in overall statistics
|
224
|
+
unless schema_report[:ignored]
|
225
|
+
@total_entities.concat(schema_report[:total])
|
226
|
+
@documented_entities.concat(schema_report[:documented])
|
227
|
+
@undocumented_entities.concat(schema_report[:undocumented].map do |entity|
|
228
|
+
{ schema: schema.id, entity: entity }
|
229
|
+
end)
|
230
|
+
end
|
190
231
|
end
|
191
232
|
end
|
192
233
|
|
@@ -200,12 +241,19 @@ module Expressir
|
|
200
241
|
|
201
242
|
coverage = entities.empty? ? 100.0 : (documented.size.to_f / entities.size) * 100
|
202
243
|
|
244
|
+
# Check if this schema file is ignored
|
245
|
+
schema_file = File.expand_path(schema.file) if schema.file
|
246
|
+
ignored = @ignored_files.key?(schema_file)
|
247
|
+
matched_pattern = @ignored_files[schema_file] if ignored
|
248
|
+
|
203
249
|
{
|
204
250
|
schema: schema,
|
205
251
|
total: entities,
|
206
252
|
documented: documented,
|
207
253
|
undocumented: undocumented.map { |e| format_entity(e) },
|
208
254
|
coverage: coverage,
|
255
|
+
ignored: ignored,
|
256
|
+
matched_pattern: matched_pattern,
|
209
257
|
}
|
210
258
|
end
|
211
259
|
|
data/lib/expressir/version.rb
CHANGED