expressir 2.1.18 → 2.1.19
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 +17 -9
- data/README.adoc +225 -3
- data/expressir.gemspec +2 -0
- data/lib/expressir/cli.rb +28 -193
- data/lib/expressir/commands/base.rb +32 -0
- data/lib/expressir/commands/benchmark.rb +68 -0
- data/lib/expressir/commands/benchmark_cache.rb +88 -0
- data/lib/expressir/commands/clean.rb +20 -0
- data/lib/expressir/commands/coverage.rb +307 -0
- data/lib/expressir/commands/format.rb +13 -0
- data/lib/expressir/commands/validate.rb +53 -0
- data/lib/expressir/commands/version.rb +9 -0
- data/lib/expressir/coverage.rb +249 -0
- data/lib/expressir/express/formatter.rb +4 -2
- data/lib/expressir/express/visitor.rb +10 -6
- data/lib/expressir/model/declarations/derived_attribute.rb +25 -0
- data/lib/expressir/model/declarations/inverse_attribute.rb +25 -0
- data/lib/expressir/model/model_element.rb +2 -0
- data/lib/expressir/version.rb +1 -1
- data/lib/expressir.rb +1 -0
- metadata +41 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b68644d000b4b7d47a7e132922afa9b4e9f1d3fb19ba6c3b9e2a8db28c5fd33
|
4
|
+
data.tar.gz: 132ecfd9ca85168335536626fea46c3648757ccd973823242b04b0744869376c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 895f018faf2bbdd075991d45fa22061459b918f907e568e4481a98dd2e0eb96a312cb98d96e2e7de381c7c85841d05631119f7c26e1773ac634377cdac8e6fe2
|
7
|
+
data.tar.gz: 025421a41b6463548b8ac099fe8b5bc94eb21ee58339f77a6ff028c59ebdb1ac27c5f24ea46050d1fa5b84ee5e80802efcb45b0a549bc733ea833f43c48e0e14
|
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-
|
3
|
+
# on 2025-06-04 17:31:42 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
|
@@ -35,13 +35,17 @@ Lint/UnusedMethodArgument:
|
|
35
35
|
- 'lib/expressir/express/cache.rb'
|
36
36
|
- 'lib/expressir/express/parser.rb'
|
37
37
|
|
38
|
-
# Offense count:
|
38
|
+
# Offense count: 71
|
39
39
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
40
40
|
Metrics/AbcSize:
|
41
41
|
Exclude:
|
42
42
|
- 'lib/expressir/benchmark.rb'
|
43
|
-
- 'lib/expressir/
|
43
|
+
- 'lib/expressir/commands/benchmark.rb'
|
44
|
+
- 'lib/expressir/commands/benchmark_cache.rb'
|
45
|
+
- 'lib/expressir/commands/coverage.rb'
|
46
|
+
- 'lib/expressir/commands/validate.rb'
|
44
47
|
- 'lib/expressir/config.rb'
|
48
|
+
- 'lib/expressir/coverage.rb'
|
45
49
|
- 'lib/expressir/express/formatter.rb'
|
46
50
|
- 'lib/expressir/express/hyperlink_formatter.rb'
|
47
51
|
- 'lib/expressir/express/parser.rb'
|
@@ -50,17 +54,19 @@ Metrics/AbcSize:
|
|
50
54
|
- 'lib/expressir/model/declarations/schema.rb'
|
51
55
|
- 'lib/expressir/model/model_element.rb'
|
52
56
|
|
53
|
-
# Offense count:
|
57
|
+
# Offense count: 1
|
54
58
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
55
59
|
# AllowedMethods: refine
|
56
60
|
Metrics/BlockLength:
|
57
|
-
Max:
|
61
|
+
Max: 143
|
58
62
|
|
59
|
-
# Offense count:
|
63
|
+
# Offense count: 51
|
60
64
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
61
65
|
Metrics/CyclomaticComplexity:
|
62
66
|
Exclude:
|
63
67
|
- 'lib/expressir/benchmark.rb'
|
68
|
+
- 'lib/expressir/commands/coverage.rb'
|
69
|
+
- 'lib/expressir/coverage.rb'
|
64
70
|
- 'lib/expressir/express/formatter.rb'
|
65
71
|
- 'lib/expressir/express/model_visitor.rb'
|
66
72
|
- 'lib/expressir/express/parser.rb'
|
@@ -69,16 +75,18 @@ Metrics/CyclomaticComplexity:
|
|
69
75
|
- 'lib/expressir/model/model_element.rb'
|
70
76
|
- 'spec/support/model_element_helper.rb'
|
71
77
|
|
72
|
-
# Offense count:
|
78
|
+
# Offense count: 94
|
73
79
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
74
80
|
Metrics/MethodLength:
|
75
|
-
Max:
|
81
|
+
Max: 50
|
76
82
|
|
77
|
-
# Offense count:
|
83
|
+
# Offense count: 39
|
78
84
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
79
85
|
Metrics/PerceivedComplexity:
|
80
86
|
Exclude:
|
81
87
|
- 'lib/expressir/benchmark.rb'
|
88
|
+
- 'lib/expressir/commands/coverage.rb'
|
89
|
+
- 'lib/expressir/coverage.rb'
|
82
90
|
- 'lib/expressir/express/formatter.rb'
|
83
91
|
- 'lib/expressir/express/visitor.rb'
|
84
92
|
- 'lib/expressir/model/declarations/schema.rb'
|
data/README.adoc
CHANGED
@@ -80,20 +80,31 @@ Commands:
|
|
80
80
|
expressir format PATH # pretty print EXPRESS schema located at PATH
|
81
81
|
expressir help [COMMAND] # Describe available commands or one specific command
|
82
82
|
expressir validate *PATH # validate EXPRESS schema located at PATH
|
83
|
+
expressir coverage *PATH # List EXPRESS entities and check documentation coverage
|
83
84
|
expressir version # Expressir Version
|
84
85
|
----
|
85
86
|
|
86
|
-
===
|
87
|
+
=== Format schema
|
88
|
+
|
89
|
+
The `format` command pretty prints an EXPRESS schema, making it more readable
|
90
|
+
while preserving its structure.
|
87
91
|
|
88
92
|
[source, sh]
|
89
93
|
----
|
94
|
+
# Pretty print a schema to stdout
|
90
95
|
expressir format schemas/resources/action_schema/action_schema.exp
|
91
96
|
----
|
92
97
|
|
98
|
+
This command:
|
99
|
+
1. Parses the EXPRESS schema
|
100
|
+
2. Formats it with consistent indentation and spacing
|
101
|
+
3. Outputs the formatted schema to stdout
|
102
|
+
|
93
103
|
=== Clean schema
|
94
104
|
|
95
|
-
The `clean` command strips remarks and prettifies EXPRESS schemas.
|
96
|
-
|
105
|
+
The `clean` command strips remarks and prettifies EXPRESS schemas. This is
|
106
|
+
useful for removing all documentation comments while maintaining the schema's
|
107
|
+
functional definition. You can optionally save the result to a file.
|
97
108
|
|
98
109
|
[source, sh]
|
99
110
|
----
|
@@ -104,6 +115,46 @@ expressir clean schemas/resources/action_schema/action_schema.exp
|
|
104
115
|
expressir clean schemas/resources/action_schema/action_schema.exp --output clean_schema.exp
|
105
116
|
----
|
106
117
|
|
118
|
+
[options="header"]
|
119
|
+
|===
|
120
|
+
| Option | Description
|
121
|
+
| `--output PATH` | Path to save the cleaned schema (optional, defaults to stdout)
|
122
|
+
|===
|
123
|
+
|
124
|
+
=== Validate schema
|
125
|
+
|
126
|
+
The `validate` command performs validation checks on EXPRESS schema files.
|
127
|
+
|
128
|
+
It verifies:
|
129
|
+
|
130
|
+
. That the schema can be parsed correctly
|
131
|
+
. That the schema includes a version string
|
132
|
+
|
133
|
+
[source, sh]
|
134
|
+
----
|
135
|
+
# Validate a single schema
|
136
|
+
expressir validate schemas/resources/action_schema/action_schema.exp
|
137
|
+
|
138
|
+
# Validate multiple schemas
|
139
|
+
expressir validate schemas/resources/action_schema/action_schema.exp schemas/resources/approval_schema/approval_schema.exp
|
140
|
+
----
|
141
|
+
|
142
|
+
The command reports any schemas that:
|
143
|
+
|
144
|
+
* Failed to parse
|
145
|
+
* Are missing a version string
|
146
|
+
|
147
|
+
If all validations pass, it will display "Validation passed for all EXPRESS schemas."
|
148
|
+
|
149
|
+
=== Version
|
150
|
+
|
151
|
+
The `version` command displays the current version of the Expressir gem.
|
152
|
+
|
153
|
+
[source, sh]
|
154
|
+
----
|
155
|
+
expressir version
|
156
|
+
----
|
157
|
+
|
107
158
|
=== Benchmarking
|
108
159
|
|
109
160
|
Expressir includes powerful benchmarking capabilities for measuring schema
|
@@ -181,6 +232,115 @@ The benchmark commands support several options:
|
|
181
232
|
When using the `--format json` option, results will be output in JSON format,
|
182
233
|
making it easy to parse for further analysis or visualization.
|
183
234
|
|
235
|
+
=== Documentation coverage
|
236
|
+
|
237
|
+
Expressir can analyze EXPRESS schemas to check for documentation coverage. This helps
|
238
|
+
identify which entities are properly documented with remarks and which ones require
|
239
|
+
documentation.
|
240
|
+
|
241
|
+
==== Analyzing documentation coverage
|
242
|
+
|
243
|
+
Use the `coverage` command to check documentation coverage of EXPRESS schemas:
|
244
|
+
|
245
|
+
[source, sh]
|
246
|
+
----
|
247
|
+
# Analyze a single EXPRESS file
|
248
|
+
expressir coverage schemas/resources/action_schema/action_schema.exp
|
249
|
+
|
250
|
+
# Analyze multiple EXPRESS files
|
251
|
+
expressir coverage schemas/resources/action_schema/action_schema.exp schemas/resources/approval_schema/approval_schema.exp
|
252
|
+
|
253
|
+
# Analyze all EXPRESS files in a directory (recursively)
|
254
|
+
expressir coverage schemas/resources/
|
255
|
+
|
256
|
+
# Analyze files specified in a YAML file
|
257
|
+
expressir coverage schemas.yml
|
258
|
+
----
|
259
|
+
|
260
|
+
The output shows which entities are missing documentation, calculates coverage percentages,
|
261
|
+
and provides an overall documentation coverage summary.
|
262
|
+
|
263
|
+
==== Coverage options
|
264
|
+
|
265
|
+
The coverage command supports different output formats and exclusion options:
|
266
|
+
|
267
|
+
[options="header"]
|
268
|
+
|===
|
269
|
+
| Option | Description
|
270
|
+
| `--format text` | (Default) Display a human-readable table with coverage information
|
271
|
+
| `--format json` | Output in JSON format for programmatic processing
|
272
|
+
| `--format yaml` | Output in YAML format for programmatic processing
|
273
|
+
| `--exclude TYPES` | Comma-separated list of EXPRESS entity types to exclude from coverage analysis
|
274
|
+
|===
|
275
|
+
|
276
|
+
==== Excluding entity types from coverage
|
277
|
+
|
278
|
+
You can exclude specific EXPRESS entity types from coverage analysis using the
|
279
|
+
`--exclude` option.
|
280
|
+
|
281
|
+
This is useful when certain entity types don't require documentation coverage,
|
282
|
+
such as TYPE entities whose descriptions are generated by template strings.
|
283
|
+
|
284
|
+
[source, sh]
|
285
|
+
----
|
286
|
+
# Exclude TYPE entities from coverage analysis
|
287
|
+
expressir coverage --exclude=TYPE schemas/resources/action_schema/action_schema.exp
|
288
|
+
|
289
|
+
# Exclude multiple entity types
|
290
|
+
expressir coverage --exclude=TYPE,CONSTANT,FUNCTION schemas/resources/action_schema/action_schema.exp
|
291
|
+
|
292
|
+
# Combine with output format options
|
293
|
+
expressir coverage --exclude=TYPE --format=json schemas/resources/action_schema/action_schema.exp
|
294
|
+
----
|
295
|
+
|
296
|
+
Valid entity types that can be excluded:
|
297
|
+
|
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
|
305
|
+
|
306
|
+
If you specify an invalid entity type, the command will display an error message
|
307
|
+
with the list of valid types.
|
308
|
+
|
309
|
+
.Example with JSON output:
|
310
|
+
[example]
|
311
|
+
====
|
312
|
+
[source, sh]
|
313
|
+
----
|
314
|
+
expressir coverage schemas/resources/ --format json
|
315
|
+
----
|
316
|
+
====
|
317
|
+
|
318
|
+
When using JSON or YAML output formats, all file and directory paths are
|
319
|
+
displayed relative to the current working directory:
|
320
|
+
|
321
|
+
[source, yaml]
|
322
|
+
----
|
323
|
+
- file: "schemas/resources/action_schema/action_schema.exp"
|
324
|
+
file_basename: action_schema.exp
|
325
|
+
directory: "schemas/resources/action_schema"
|
326
|
+
# ... other fields
|
327
|
+
----
|
328
|
+
|
329
|
+
==== Coverage output
|
330
|
+
|
331
|
+
The default text output displays:
|
332
|
+
|
333
|
+
. Directory coverage (when analyzing multiple directories)
|
334
|
+
|
335
|
+
. File coverage, showing:
|
336
|
+
** File path
|
337
|
+
** List of undocumented entities
|
338
|
+
** Coverage percentage
|
339
|
+
|
340
|
+
. Overall documentation coverage statistics
|
341
|
+
|
342
|
+
This helps identify areas of your EXPRESS schemas that need documentation
|
343
|
+
improvement.
|
184
344
|
|
185
345
|
|
186
346
|
== Usage: Ruby
|
@@ -318,6 +478,68 @@ schema = repo_drop.schemas.first
|
|
318
478
|
schema.file = "path/to/file.exp"
|
319
479
|
----
|
320
480
|
|
481
|
+
=== Documentation coverage analysis
|
482
|
+
|
483
|
+
Expressir's documentation coverage feature can be used programmatically to
|
484
|
+
analyze and report on documentation coverage of EXPRESS schemas.
|
485
|
+
|
486
|
+
[source,ruby]
|
487
|
+
----
|
488
|
+
# Create a coverage report from a file
|
489
|
+
report = Expressir::Coverage::Report.from_file("path/to/schema.exp")
|
490
|
+
|
491
|
+
# Or create a report from a repository
|
492
|
+
repository = Expressir::Express::Parser.from_file("path/to/schema.exp")
|
493
|
+
report = Expressir::Coverage::Report.from_repository(repository)
|
494
|
+
|
495
|
+
# Access overall statistics
|
496
|
+
puts "Overall coverage: #{report.coverage_percentage}%"
|
497
|
+
puts "Total entities: #{report.total_entities.size}"
|
498
|
+
puts "Documented entities: #{report.documented_entities.size}"
|
499
|
+
puts "Undocumented entities: #{report.undocumented_entities.size}"
|
500
|
+
|
501
|
+
# Access file-level reports
|
502
|
+
report.file_reports.each do |file_report|
|
503
|
+
puts "File: #{file_report[:file]}"
|
504
|
+
puts " Coverage: #{file_report[:coverage]}%"
|
505
|
+
puts " Total entities: #{file_report[:total]}"
|
506
|
+
puts " Documented entities: #{file_report[:documented]}"
|
507
|
+
puts " Undocumented entities: #{file_report[:undocumented].join(', ')}"
|
508
|
+
end
|
509
|
+
|
510
|
+
# Access directory-level reports
|
511
|
+
report.directory_reports.each do |dir_report|
|
512
|
+
puts "Directory: #{dir_report[:directory]}"
|
513
|
+
puts " Coverage: #{dir_report[:coverage]}%"
|
514
|
+
puts " Total entities: #{dir_report[:total]}"
|
515
|
+
puts " Documented entities: #{dir_report[:documented]}"
|
516
|
+
puts " Undocumented entities: #{dir_report[:undocumented]}"
|
517
|
+
puts " Number of files: #{dir_report[:files]}"
|
518
|
+
end
|
519
|
+
|
520
|
+
# Generate a structured hash representation
|
521
|
+
report_hash = report.to_h # Contains overall, directories and files sections
|
522
|
+
----
|
523
|
+
|
524
|
+
You can also use the core methods directly to check documentation status:
|
525
|
+
|
526
|
+
[source,ruby]
|
527
|
+
----
|
528
|
+
# Check if an entity has documentation
|
529
|
+
schema = repository.schemas.first
|
530
|
+
entity = schema.entities.first
|
531
|
+
|
532
|
+
if Expressir::Coverage.entity_documented?(entity)
|
533
|
+
puts "Entity #{entity.id} is documented"
|
534
|
+
else
|
535
|
+
puts "Entity #{entity.id} is not documented"
|
536
|
+
end
|
537
|
+
|
538
|
+
# Find all entities in a schema
|
539
|
+
all_entities = Expressir::Coverage.find_entities(schema)
|
540
|
+
puts "Found #{all_entities.size} entities in schema #{schema.id}"
|
541
|
+
----
|
542
|
+
|
321
543
|
|
322
544
|
== Contributing
|
323
545
|
|
data/expressir.gemspec
CHANGED
@@ -39,6 +39,8 @@ Gem::Specification.new do |spec|
|
|
39
39
|
spec.add_dependency "liquid"
|
40
40
|
spec.add_dependency "lutaml-model", "~>0.7"
|
41
41
|
spec.add_dependency "parslet", "~> 2.0"
|
42
|
+
spec.add_dependency "ruby-progressbar", "~> 1.11"
|
43
|
+
spec.add_dependency "terminal-table", "~> 3.0"
|
42
44
|
spec.add_dependency "thor", "~> 1.0"
|
43
45
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
44
46
|
end
|
data/lib/expressir/cli.rb
CHANGED
@@ -1,32 +1,32 @@
|
|
1
1
|
require "thor"
|
2
2
|
require "yaml"
|
3
|
+
require "terminal-table"
|
4
|
+
|
5
|
+
require_relative "commands/base"
|
6
|
+
require_relative "commands/format"
|
7
|
+
require_relative "commands/clean"
|
8
|
+
require_relative "commands/benchmark"
|
9
|
+
require_relative "commands/benchmark_cache"
|
10
|
+
require_relative "commands/validate"
|
11
|
+
require_relative "commands/coverage"
|
12
|
+
require_relative "commands/version"
|
3
13
|
|
4
14
|
module Expressir
|
5
15
|
class Cli < Thor
|
16
|
+
# Exit with error code on command failures
|
17
|
+
def self.exit_on_failure?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
6
21
|
desc "format PATH", "pretty print EXPRESS schema located at PATH"
|
7
22
|
def format(path)
|
8
|
-
|
9
|
-
repository.schemas.each do |schema|
|
10
|
-
puts "\n(* Expressir formatted schema: #{schema.id} *)\n"
|
11
|
-
puts schema.to_s(no_remarks: true)
|
12
|
-
end
|
23
|
+
Commands::Format.new(options).run(path)
|
13
24
|
end
|
14
25
|
|
15
26
|
desc "clean PATH", "Strip remarks and prettify EXPRESS schema at PATH"
|
16
27
|
method_option :output, type: :string, desc: "Output file path (defaults to stdout)"
|
17
28
|
def clean(path)
|
18
|
-
|
19
|
-
formatted_schemas = repository.schemas.map do |schema|
|
20
|
-
# Format schema without remarks
|
21
|
-
schema.to_s(no_remarks: true)
|
22
|
-
end.join("\n\n")
|
23
|
-
|
24
|
-
if options[:output]
|
25
|
-
File.write(options[:output], formatted_schemas)
|
26
|
-
puts "Cleaned schema written to #{options[:output]}"
|
27
|
-
else
|
28
|
-
puts formatted_schemas
|
29
|
-
end
|
29
|
+
Commands::Clean.new(options).run(path)
|
30
30
|
end
|
31
31
|
|
32
32
|
desc "benchmark FILE_OR_YAML", "Benchmark schema loading performance for a file or list of files from YAML"
|
@@ -35,18 +35,7 @@ module Expressir
|
|
35
35
|
method_option :save, type: :boolean, desc: "Save benchmark results to file"
|
36
36
|
method_option :format, type: :string, desc: "Output format (json, csv, default)"
|
37
37
|
def benchmark(path)
|
38
|
-
|
39
|
-
Expressir.configuration.benchmark_enabled = true
|
40
|
-
Expressir.configuration.benchmark_ips = options[:ips]
|
41
|
-
Expressir.configuration.benchmark_verbose = options[:verbose]
|
42
|
-
Expressir.configuration.benchmark_save = options[:save]
|
43
|
-
Expressir.configuration.benchmark_format = options[:format] if options[:format]
|
44
|
-
|
45
|
-
if [".yml", ".yaml"].include?(File.extname(path).downcase)
|
46
|
-
benchmark_from_yaml(path)
|
47
|
-
else
|
48
|
-
benchmark_file(path)
|
49
|
-
end
|
38
|
+
Commands::Benchmark.new(options).run(path)
|
50
39
|
end
|
51
40
|
|
52
41
|
desc "benchmark-cache FILE_OR_YAML", "Benchmark schema loading with caching"
|
@@ -56,178 +45,24 @@ module Expressir
|
|
56
45
|
method_option :format, type: :string, desc: "Output format (json, csv, default)"
|
57
46
|
method_option :cache_path, type: :string, desc: "Path to store the cache file"
|
58
47
|
def benchmark_cache(path)
|
59
|
-
|
60
|
-
Expressir.configuration.benchmark_enabled = true
|
61
|
-
Expressir.configuration.benchmark_ips = options[:ips]
|
62
|
-
Expressir.configuration.benchmark_verbose = options[:verbose]
|
63
|
-
Expressir.configuration.benchmark_save = options[:save]
|
64
|
-
Expressir.configuration.benchmark_format = options[:format] if options[:format]
|
65
|
-
|
66
|
-
# Run benchmarks with cache
|
67
|
-
cache_path = options[:cache_path] || generate_temp_cache_path
|
68
|
-
|
69
|
-
if [".yml", ".yaml"].include?(File.extname(path).downcase)
|
70
|
-
benchmark_cache_from_yaml(path, cache_path)
|
71
|
-
else
|
72
|
-
benchmark_cache_file(path, cache_path)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
no_commands do
|
77
|
-
def _validate_schema(path)
|
78
|
-
repository = Expressir::Express::Parser.from_file(path)
|
79
|
-
repository.schemas.inject([]) do |acc, schema|
|
80
|
-
acc << schema.id unless schema.version&.value
|
81
|
-
acc
|
82
|
-
end
|
83
|
-
rescue StandardError
|
84
|
-
nil
|
85
|
-
end
|
86
|
-
|
87
|
-
def _print_validation_errors(type, array)
|
88
|
-
return if array.empty?
|
89
|
-
|
90
|
-
puts "#{'*' * 20} RESULTS: #{type.to_s.upcase.tr('_', ' ')} #{'*' * 20}"
|
91
|
-
array.each do |msg|
|
92
|
-
puts msg
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def benchmark_file(path)
|
97
|
-
puts "Express Schema Loading Benchmark"
|
98
|
-
puts "--------------------------------"
|
99
|
-
|
100
|
-
repository = Expressir::Benchmark.measure_file(path) do
|
101
|
-
Expressir::Express::Parser.from_file(path)
|
102
|
-
end
|
103
|
-
|
104
|
-
if repository
|
105
|
-
puts "Loaded #{repository.schemas.size} schemas"
|
106
|
-
else
|
107
|
-
puts "Failed to load schema"
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def benchmark_from_yaml(yaml_path)
|
112
|
-
puts "Express Schema Loading Benchmark from YAML"
|
113
|
-
puts "--------------------------------"
|
114
|
-
|
115
|
-
# Load schema list from YAML
|
116
|
-
schema_list = YAML.load_file(yaml_path)
|
117
|
-
if schema_list.is_a?(Hash) && schema_list["schemas"]
|
118
|
-
# Handle format: { "schemas": ["path1", "path2", ...] }
|
119
|
-
schema_files = schema_list["schemas"]
|
120
|
-
elsif schema_list.is_a?(Array)
|
121
|
-
# Handle format: ["path1", "path2", ...]
|
122
|
-
schema_files = schema_list
|
123
|
-
else
|
124
|
-
puts "Invalid YAML format. Expected an array of schema paths or a hash with a 'schemas' key."
|
125
|
-
return
|
126
|
-
end
|
127
|
-
|
128
|
-
puts "YAML File: #{yaml_path}"
|
129
|
-
puts "Number of schemas in list: #{schema_files.size}"
|
130
|
-
puts "--------------------------------"
|
131
|
-
|
132
|
-
# Load the schemas
|
133
|
-
Expressir::Benchmark.measure_collection(schema_files) do |file|
|
134
|
-
repository = Expressir::Express::Parser.from_file(file)
|
135
|
-
repository.schemas
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def benchmark_cache_file(path, cache_path)
|
140
|
-
puts "Express Schema Loading Benchmark with Caching"
|
141
|
-
puts "--------------------------------"
|
142
|
-
puts "Schema: #{path}"
|
143
|
-
puts "Cache: #{cache_path}"
|
144
|
-
puts "--------------------------------"
|
145
|
-
|
146
|
-
# Benchmark with caching
|
147
|
-
results = Expressir::Benchmark.measure_with_cache(path, cache_path) do |file|
|
148
|
-
Expressir::Express::Parser.from_file(file)
|
149
|
-
end
|
150
|
-
|
151
|
-
if results[:repository]
|
152
|
-
schema_count = results[:repository].schemas.size
|
153
|
-
puts "Loaded #{schema_count} schemas"
|
154
|
-
else
|
155
|
-
puts "Failed to load schema"
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def benchmark_cache_from_yaml(yaml_path, cache_path)
|
160
|
-
puts "Express Schema Loading Benchmark with Caching from YAML"
|
161
|
-
puts "--------------------------------"
|
162
|
-
|
163
|
-
# Load schema list from YAML
|
164
|
-
schema_list = YAML.load_file(yaml_path)
|
165
|
-
if schema_list.is_a?(Hash) && schema_list["schemas"]
|
166
|
-
# Handle format: { "schemas": ["path1", "path2", ...] }
|
167
|
-
schema_files = schema_list["schemas"]
|
168
|
-
elsif schema_list.is_a?(Array)
|
169
|
-
# Handle format: ["path1", "path2", ...]
|
170
|
-
schema_files = schema_list
|
171
|
-
else
|
172
|
-
puts "Invalid YAML format. Expected an array of schema paths or a hash with a 'schemas' key."
|
173
|
-
return
|
174
|
-
end
|
175
|
-
|
176
|
-
puts "YAML File: #{yaml_path}"
|
177
|
-
puts "Number of schemas in list: #{schema_files.size}"
|
178
|
-
puts "Cache: #{cache_path}"
|
179
|
-
puts "--------------------------------"
|
180
|
-
|
181
|
-
# Process each file with caching
|
182
|
-
schema_files.each_with_index do |file, index|
|
183
|
-
puts "Processing file #{index + 1}/#{schema_files.size}: #{file}"
|
184
|
-
|
185
|
-
# Benchmark with caching
|
186
|
-
Expressir::Benchmark.measure_with_cache(file, cache_path) do |path|
|
187
|
-
Expressir::Express::Parser.from_file(path)
|
188
|
-
end
|
189
|
-
|
190
|
-
puts "--------------------------------"
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def generate_temp_cache_path
|
195
|
-
require "tempfile"
|
196
|
-
Tempfile.new(["expressir_cache", ".bin"]).path
|
197
|
-
end
|
48
|
+
Commands::BenchmarkCache.new(options).run(path)
|
198
49
|
end
|
199
50
|
|
200
51
|
desc "validate *PATH", "validate EXPRESS schema located at PATH"
|
201
|
-
def validate(*paths)
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
paths.each do |path|
|
206
|
-
x = Pathname.new(path).realpath.relative_path_from(Dir.pwd)
|
207
|
-
puts "Validating #{x}"
|
208
|
-
ret = _validate_schema(path)
|
209
|
-
|
210
|
-
if ret.nil?
|
211
|
-
no_valid << "Failed to parse: #{x}"
|
212
|
-
next
|
213
|
-
end
|
214
|
-
|
215
|
-
ret.each do |schema_id|
|
216
|
-
no_version << "Missing version string: schema `#{schema_id}` | #{x}"
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
_print_validation_errors(:failed_to_parse, no_valid)
|
221
|
-
_print_validation_errors(:missing_version_string, no_version)
|
222
|
-
|
223
|
-
exit 1 unless [no_valid, no_version].all?(&:empty?)
|
52
|
+
def validate(*paths)
|
53
|
+
Commands::Validate.new(options).run(paths)
|
54
|
+
end
|
224
55
|
|
225
|
-
|
56
|
+
desc "coverage *PATH", "List EXPRESS entities and check documentation coverage"
|
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)"
|
59
|
+
def coverage(*paths)
|
60
|
+
Commands::Coverage.new(options).run(paths)
|
226
61
|
end
|
227
62
|
|
228
63
|
desc "version", "Expressir Version"
|
229
64
|
def version
|
230
|
-
|
65
|
+
Commands::Version.new(options).run
|
231
66
|
end
|
232
67
|
end
|
233
68
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Expressir
|
2
|
+
module Commands
|
3
|
+
class Base
|
4
|
+
attr_reader :options
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
# Common utilities that all commands might need
|
11
|
+
def say(message)
|
12
|
+
# Use instance variable for testability - if output is set, use it
|
13
|
+
if defined?(@output) && @output
|
14
|
+
@output.puts(message)
|
15
|
+
else
|
16
|
+
puts(message)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def exit_with_error(message, exit_code = 1)
|
21
|
+
say message
|
22
|
+
# In test mode, raise an exception instead of exiting
|
23
|
+
# This makes it easier to test error cases
|
24
|
+
if defined?(@test_mode) && @test_mode
|
25
|
+
raise message # Just raise the message as an exception
|
26
|
+
else
|
27
|
+
exit exit_code
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|