class-metrix 1.0.0 → 1.0.1
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/.vscode/README.md +103 -47
- data/.vscode/extensions.json +10 -7
- data/.vscode/keybindings.json +26 -0
- data/.vscode/rbs.code-snippets +61 -0
- data/.vscode/settings.json +25 -1
- data/.vscode/tasks.json +141 -0
- data/CHANGELOG.md +2 -0
- data/README.md +46 -16
- data/Steepfile +26 -0
- data/docs/CHANGELOG_EVOLUTION_EXAMPLE.md +95 -0
- data/lib/class_metrix/extractor.rb +1 -1
- data/lib/class_metrix/extractors/constants_extractor.rb +1 -1
- data/lib/class_metrix/extractors/methods_extractor.rb +1 -1
- data/lib/class_metrix/extractors/multi_type_extractor.rb +2 -2
- data/lib/class_metrix/formatters/base/base_formatter.rb +3 -3
- data/lib/class_metrix/formatters/components/footer_component.rb +3 -3
- data/lib/class_metrix/formatters/components/generic_header_component.rb +2 -2
- data/lib/class_metrix/formatters/components/header_component.rb +4 -4
- data/lib/class_metrix/formatters/components/missing_behaviors_component.rb +7 -7
- data/lib/class_metrix/formatters/components/table_component/row_processor.rb +8 -5
- data/lib/class_metrix/formatters/components/table_component/table_data_extractor.rb +4 -1
- data/lib/class_metrix/formatters/components/table_component/table_renderer.rb +2 -2
- data/lib/class_metrix/formatters/components/table_component.rb +5 -4
- data/lib/class_metrix/formatters/csv_formatter.rb +3 -3
- data/lib/class_metrix/formatters/markdown_formatter.rb +3 -4
- data/lib/class_metrix/formatters/shared/markdown_table_builder.rb +2 -2
- data/lib/class_metrix/formatters/shared/table_builder.rb +8 -6
- data/lib/class_metrix/version.rb +1 -1
- data/sig/class_metrix.rbs +8 -0
- data/sig/extractor.rbs +54 -0
- data/sig/extractors.rbs +84 -0
- data/sig/formatters_base.rbs +59 -0
- data/sig/formatters_components.rbs +133 -0
- data/sig/formatters_main.rbs +20 -0
- data/sig/formatters_shared.rbs +102 -0
- data/sig/manifest.yaml +32 -0
- data/sig/utils.rbs +57 -0
- data/sig/value_processor.rbs +11 -0
- data/sig/version.rbs +4 -0
- metadata +44 -2
- data/sig/class/metrix.rbs +0 -6
data/README.md
CHANGED
@@ -5,10 +5,12 @@
|
|
5
5
|
|
6
6
|
**ClassMetrix** is a Ruby gem that extracts and compares class behaviors (constants, class methods, and more) across multiple classes, generating clean markdown reports for analysis, documentation, and compliance auditing.
|
7
7
|
|
8
|
+
> **Why "Metrix"?** Short for "metrics" - measuring and analyzing class behaviors.
|
9
|
+
|
8
10
|
## ✨ Features
|
9
11
|
|
10
12
|
- **🔍 Multi-Type Extraction**: Constants, class methods, and more
|
11
|
-
- **📊 Hash Expansion**: Expand hash values into readable sub-rows
|
13
|
+
- **📊 Hash Expansion**: Expand hash values into readable sub-rows
|
12
14
|
- **🛡️ Error Handling**: Graceful handling of missing methods and constants
|
13
15
|
- **🐛 Debug Mode**: Detailed logging for troubleshooting and analysis
|
14
16
|
- **📝 Rich Markdown Reports**: Professional reports with configurable components
|
@@ -30,7 +32,7 @@ ClassMetrix.extract(:constants, :class_methods)
|
|
30
32
|
.filter(/config$/)
|
31
33
|
.expand_hashes
|
32
34
|
.handle_errors
|
33
|
-
.to_markdown("audit_report.md",
|
35
|
+
.to_markdown("audit_report.md",
|
34
36
|
title: "Service Configuration Audit",
|
35
37
|
footer_style: :detailed,
|
36
38
|
show_missing_summary: true
|
@@ -40,7 +42,7 @@ ClassMetrix.extract(:constants, :class_methods)
|
|
40
42
|
ClassMetrix.extract(:constants)
|
41
43
|
.from([DatabaseConfig, RedisConfig])
|
42
44
|
.expand_hashes
|
43
|
-
.to_csv("config_analysis.csv",
|
45
|
+
.to_csv("config_analysis.csv",
|
44
46
|
title: "Configuration Analysis",
|
45
47
|
flatten_hashes: true
|
46
48
|
)
|
@@ -65,6 +67,7 @@ gem install class-metrix
|
|
65
67
|
### Basic Extraction
|
66
68
|
|
67
69
|
#### Constants
|
70
|
+
|
68
71
|
```ruby
|
69
72
|
# Extract constants from multiple classes
|
70
73
|
ClassMetrix.extract(:constants)
|
@@ -79,6 +82,7 @@ ClassMetrix.extract(:constants)
|
|
79
82
|
```
|
80
83
|
|
81
84
|
#### Class Methods
|
85
|
+
|
82
86
|
```ruby
|
83
87
|
# Extract class method results
|
84
88
|
ClassMetrix.extract(:class_methods)
|
@@ -94,6 +98,7 @@ ClassMetrix.extract(:class_methods)
|
|
94
98
|
```
|
95
99
|
|
96
100
|
#### Multi-Type Extraction
|
101
|
+
|
97
102
|
```ruby
|
98
103
|
# Combine multiple extraction types in one table
|
99
104
|
ClassMetrix.extract(:constants, :class_methods)
|
@@ -110,6 +115,7 @@ ClassMetrix.extract(:constants, :class_methods)
|
|
110
115
|
### Advanced Features
|
111
116
|
|
112
117
|
#### Hash Expansion
|
118
|
+
|
113
119
|
```ruby
|
114
120
|
# Expand hash values into readable sub-rows
|
115
121
|
ClassMetrix.extract(:constants)
|
@@ -127,6 +133,7 @@ ClassMetrix.extract(:constants)
|
|
127
133
|
```
|
128
134
|
|
129
135
|
#### Error Handling
|
136
|
+
|
130
137
|
```ruby
|
131
138
|
# Handle missing methods and constants gracefully
|
132
139
|
ClassMetrix.extract(:class_methods)
|
@@ -144,6 +151,7 @@ ClassMetrix.extract(:class_methods)
|
|
144
151
|
```
|
145
152
|
|
146
153
|
#### Filtering
|
154
|
+
|
147
155
|
```ruby
|
148
156
|
# Filter behaviors by pattern
|
149
157
|
ClassMetrix.extract(:constants)
|
@@ -159,6 +167,7 @@ ClassMetrix.extract(:class_methods)
|
|
159
167
|
```
|
160
168
|
|
161
169
|
#### Debug Mode
|
170
|
+
|
162
171
|
```ruby
|
163
172
|
# Enable detailed logging for troubleshooting
|
164
173
|
ClassMetrix.extract(:constants, :class_methods)
|
@@ -185,17 +194,20 @@ ClassMetrix.extract(:constants)
|
|
185
194
|
```
|
186
195
|
|
187
196
|
**Debug Levels:**
|
197
|
+
|
188
198
|
- **`:basic`** (default) - Key decisions and summaries only
|
189
|
-
- **`:detailed`** - More context and intermediate steps
|
199
|
+
- **`:detailed`** - More context and intermediate steps
|
190
200
|
- **`:verbose`** - Full details including individual value processing
|
191
201
|
|
192
202
|
**Debug Features:**
|
203
|
+
|
193
204
|
- **Safe Object Inspection**: Handles objects with problematic `inspect`/`to_s` methods
|
194
205
|
- **Hash Detection Analysis**: Shows why objects are/aren't treated as expandable hashes
|
195
206
|
- **Smart Logging**: Reduces spam by grouping related operations and focusing on key decisions
|
196
207
|
- **Error Diagnostics**: Detailed error context for troubleshooting
|
197
208
|
|
198
209
|
#### CSV Output
|
210
|
+
|
199
211
|
```ruby
|
200
212
|
# Basic CSV output
|
201
213
|
ClassMetrix.extract(:constants)
|
@@ -229,6 +241,7 @@ ClassMetrix.extract(:class_methods)
|
|
229
241
|
ClassMetrix offers extensive configuration options for customizing report generation:
|
230
242
|
|
231
243
|
### Markdown Report Options
|
244
|
+
|
232
245
|
```ruby
|
233
246
|
ClassMetrix.extract(:constants)
|
234
247
|
.from([User, Admin])
|
@@ -236,30 +249,31 @@ ClassMetrix.extract(:constants)
|
|
236
249
|
# File and title
|
237
250
|
"report.md",
|
238
251
|
title: "Custom Report Title",
|
239
|
-
|
252
|
+
|
240
253
|
# Content sections
|
241
254
|
show_metadata: true, # Show title and report info
|
242
255
|
show_classes: true, # Show "Classes Analyzed" section
|
243
256
|
show_extraction_info: true, # Show "Extraction Types" section
|
244
257
|
show_missing_summary: false, # Show missing behaviors summary
|
245
|
-
|
258
|
+
|
246
259
|
# Footer configuration
|
247
260
|
show_footer: true, # Show footer
|
248
261
|
footer_style: :detailed, # :default, :minimal, :detailed
|
249
262
|
show_timestamp: true, # Include generation timestamp
|
250
263
|
custom_footer: "Custom note", # Custom footer message
|
251
|
-
|
264
|
+
|
252
265
|
# Table formatting
|
253
266
|
table_style: :standard, # :standard, :compact, :wide
|
254
267
|
min_column_width: 3, # Minimum column width
|
255
268
|
max_column_width: 50, # Maximum column width (for :compact style)
|
256
|
-
|
269
|
+
|
257
270
|
# Missing behaviors analysis
|
258
271
|
summary_style: :grouped # :grouped, :flat, :detailed
|
259
272
|
)
|
260
273
|
```
|
261
274
|
|
262
275
|
### CSV Output Options
|
276
|
+
|
263
277
|
```ruby
|
264
278
|
ClassMetrix.extract(:constants)
|
265
279
|
.from([User, Admin])
|
@@ -267,16 +281,16 @@ ClassMetrix.extract(:constants)
|
|
267
281
|
# File and title
|
268
282
|
"report.csv",
|
269
283
|
title: "Custom CSV Report",
|
270
|
-
|
284
|
+
|
271
285
|
# Content options
|
272
286
|
show_metadata: true, # Show comment headers
|
273
287
|
comment_char: "#", # Comment character for metadata
|
274
|
-
|
288
|
+
|
275
289
|
# CSV formatting
|
276
290
|
separator: ",", # Column separator (comma, semicolon, tab)
|
277
291
|
quote_char: '"', # Quote character
|
278
292
|
null_value: "", # Value for nil/missing data
|
279
|
-
|
293
|
+
|
280
294
|
# Hash handling
|
281
295
|
flatten_hashes: true, # Flatten hashes into separate columns
|
282
296
|
# false = expand into sub-rows
|
@@ -286,20 +300,26 @@ ClassMetrix.extract(:constants)
|
|
286
300
|
### Footer Styles
|
287
301
|
|
288
302
|
#### Default Footer
|
303
|
+
|
289
304
|
```markdown
|
290
305
|
---
|
291
|
-
|
306
|
+
|
307
|
+
_Report generated by ClassMetrix gem_
|
292
308
|
```
|
293
309
|
|
294
310
|
#### Minimal Footer
|
311
|
+
|
295
312
|
```markdown
|
296
313
|
---
|
297
|
-
|
314
|
+
|
315
|
+
_Generated by ClassMetrix_
|
298
316
|
```
|
299
317
|
|
300
318
|
#### Detailed Footer
|
319
|
+
|
301
320
|
```markdown
|
302
321
|
---
|
322
|
+
|
303
323
|
## Report Information
|
304
324
|
|
305
325
|
- **Generated by**: [ClassMetrix gem](https://github.com/patrick204nqh/class-metrix)
|
@@ -310,18 +330,22 @@ ClassMetrix.extract(:constants)
|
|
310
330
|
### Missing Behaviors Styles
|
311
331
|
|
312
332
|
#### Grouped (Default)
|
333
|
+
|
313
334
|
```markdown
|
314
335
|
## Missing Behaviors Summary
|
315
336
|
|
316
337
|
### DatabaseConfig
|
338
|
+
|
317
339
|
- `redis_config` - 🚫 Not defined
|
318
340
|
- `cache_timeout` - 🚫 No method
|
319
341
|
|
320
|
-
### RedisConfig
|
342
|
+
### RedisConfig
|
343
|
+
|
321
344
|
- `db_config` - 🚫 Not defined
|
322
345
|
```
|
323
346
|
|
324
347
|
#### Flat
|
348
|
+
|
325
349
|
```markdown
|
326
350
|
## Missing Behaviors
|
327
351
|
|
@@ -331,22 +355,26 @@ ClassMetrix.extract(:constants)
|
|
331
355
|
```
|
332
356
|
|
333
357
|
#### Detailed
|
358
|
+
|
334
359
|
```markdown
|
335
360
|
## Missing Behaviors Analysis
|
336
361
|
|
337
362
|
**Summary**: 3 missing behaviors across 2 classes
|
338
363
|
|
339
364
|
### 🚫 Not (2 items)
|
365
|
+
|
340
366
|
- **DatabaseConfig**: `redis_config` - 🚫 Not defined
|
341
367
|
- **RedisConfig**: `db_config` - 🚫 Not defined
|
342
368
|
|
343
369
|
### 🚫 No (1 items)
|
370
|
+
|
344
371
|
- **DatabaseConfig**: `cache_timeout` - 🚫 No method
|
345
372
|
```
|
346
373
|
|
347
374
|
## 🎯 Real-World Examples
|
348
375
|
|
349
376
|
### Microservices Configuration Audit
|
377
|
+
|
350
378
|
```ruby
|
351
379
|
# Audit configuration consistency across services
|
352
380
|
services = [DatabaseService, RedisService, S3Service, AuthService]
|
@@ -365,6 +393,7 @@ ClassMetrix.extract(:constants, :class_methods)
|
|
365
393
|
```
|
366
394
|
|
367
395
|
### Policy Classes Comparison
|
396
|
+
|
368
397
|
```ruby
|
369
398
|
# Compare authorization policies
|
370
399
|
policies = [UserPolicy, AdminPolicy, ModeratorPolicy]
|
@@ -379,6 +408,7 @@ ClassMetrix.extract(:constants)
|
|
379
408
|
```
|
380
409
|
|
381
410
|
### API Version Compatibility
|
411
|
+
|
382
412
|
```ruby
|
383
413
|
# Check API compatibility across versions
|
384
414
|
apis = [V1::UsersAPI, V2::UsersAPI, V3::UsersAPI]
|
@@ -401,7 +431,7 @@ ClassMetrix uses a modular component architecture for maximum flexibility:
|
|
401
431
|
```
|
402
432
|
MarkdownFormatter
|
403
433
|
├── HeaderComponent # Title, classes, extraction info
|
404
|
-
├── TableComponent # Table formatting and hash expansion
|
434
|
+
├── TableComponent # Table formatting and hash expansion
|
405
435
|
├── MissingBehaviorsComponent # Missing behavior analysis
|
406
436
|
└── FooterComponent # Footer with various styles
|
407
437
|
```
|
@@ -428,7 +458,7 @@ ruby examples/advanced/hash_expansion.rb
|
|
428
458
|
|
429
459
|
## 📋 Requirements
|
430
460
|
|
431
|
-
- Ruby 2.7+
|
461
|
+
- Ruby 2.7+
|
432
462
|
- No runtime dependencies (pure Ruby implementation)
|
433
463
|
|
434
464
|
## 🤝 Contributing
|
data/Steepfile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Steepfile for ClassMetrix gem
|
4
|
+
D = Steep::Diagnostic
|
5
|
+
|
6
|
+
target :lib do
|
7
|
+
signature "sig"
|
8
|
+
|
9
|
+
check "lib"
|
10
|
+
|
11
|
+
# Configure libraries
|
12
|
+
library "pathname"
|
13
|
+
library "csv"
|
14
|
+
library "json"
|
15
|
+
library "fileutils"
|
16
|
+
|
17
|
+
# Configure typing options
|
18
|
+
configure_code_diagnostics(D::Ruby.default)
|
19
|
+
|
20
|
+
# Disable some noisy diagnostics for better development experience
|
21
|
+
configure_code_diagnostics do |hash|
|
22
|
+
hash[D::Ruby::UnresolvedOverloading] = :information
|
23
|
+
hash[D::Ruby::FallbackAny] = :information
|
24
|
+
hash[D::Ruby::ImplicitBreakValueMismatch] = :hint
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# ClassMetrix Changelog Evolution Example
|
2
|
+
|
3
|
+
## Current State (v1.0.0 released)
|
4
|
+
|
5
|
+
```markdown
|
6
|
+
## [Unreleased]
|
7
|
+
|
8
|
+
## [1.0.0] - 2025-06-07
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
- Advanced Debug System
|
13
|
+
- Enhanced Hash Expansion
|
14
|
+
|
15
|
+
# ... existing content
|
16
|
+
```
|
17
|
+
|
18
|
+
## After working on some features
|
19
|
+
|
20
|
+
```markdown
|
21
|
+
## [Unreleased]
|
22
|
+
|
23
|
+
### Added
|
24
|
+
|
25
|
+
- Instance variable extraction support
|
26
|
+
- New output format: JSON
|
27
|
+
- CLI interface for command-line usage
|
28
|
+
|
29
|
+
### Changed
|
30
|
+
|
31
|
+
- Improved performance for large class hierarchies
|
32
|
+
- Better error messages with suggestions
|
33
|
+
|
34
|
+
### Fixed
|
35
|
+
|
36
|
+
- Memory leak in hash expansion
|
37
|
+
- CSV encoding issues with special characters
|
38
|
+
|
39
|
+
## [1.0.0] - 2025-06-07
|
40
|
+
|
41
|
+
# ... existing content
|
42
|
+
```
|
43
|
+
|
44
|
+
## Ready for v1.1.0 release
|
45
|
+
|
46
|
+
```markdown
|
47
|
+
## [Unreleased]
|
48
|
+
|
49
|
+
## [1.1.0] - 2025-07-15
|
50
|
+
|
51
|
+
### Added
|
52
|
+
|
53
|
+
- Instance variable extraction support
|
54
|
+
- New output format: JSON
|
55
|
+
- CLI interface for command-line usage
|
56
|
+
|
57
|
+
### Changed
|
58
|
+
|
59
|
+
- Improved performance for large class hierarchies
|
60
|
+
- Better error messages with suggestions
|
61
|
+
|
62
|
+
### Fixed
|
63
|
+
|
64
|
+
- Memory leak in hash expansion
|
65
|
+
- CSV encoding issues with special characters
|
66
|
+
|
67
|
+
## [1.0.0] - 2025-06-07
|
68
|
+
|
69
|
+
# ... existing content
|
70
|
+
```
|
71
|
+
|
72
|
+
## Working on next features
|
73
|
+
|
74
|
+
```markdown
|
75
|
+
## [Unreleased]
|
76
|
+
|
77
|
+
### Added
|
78
|
+
|
79
|
+
- Plugin system for custom extractors
|
80
|
+
- Web UI for interactive analysis
|
81
|
+
|
82
|
+
### Changed
|
83
|
+
|
84
|
+
- Refactored formatter architecture
|
85
|
+
|
86
|
+
## [1.1.0] - 2025-07-15
|
87
|
+
|
88
|
+
### Added
|
89
|
+
|
90
|
+
- Instance variable extraction support
|
91
|
+
- New output format: JSON
|
92
|
+
- CLI interface for command-line usage
|
93
|
+
|
94
|
+
# ... etc
|
95
|
+
```
|
@@ -48,7 +48,7 @@ module ClassMetrix
|
|
48
48
|
@debug_mode = true
|
49
49
|
@debug_level = level
|
50
50
|
@logger = Utils::DebugLogger.new("Extractor", @debug_mode, level)
|
51
|
-
@logger
|
51
|
+
@logger&.log("Debug mode enabled (level: #{level})")
|
52
52
|
self
|
53
53
|
end
|
54
54
|
|
@@ -20,7 +20,7 @@ module ClassMetrix
|
|
20
20
|
# Build headers: ["Type", "Behavior", "Class1", "Class2", ...]
|
21
21
|
headers = %w[Type Behavior] + @classes.map(&:name)
|
22
22
|
|
23
|
-
all_rows = []
|
23
|
+
all_rows = [] # : Array[Array[untyped]]
|
24
24
|
|
25
25
|
@types.each do |type|
|
26
26
|
type_data = extract_single_type(type)
|
@@ -28,7 +28,7 @@ module ClassMetrix
|
|
28
28
|
# Add rows with type prefix
|
29
29
|
type_data[:rows].each do |row|
|
30
30
|
behavior_name = row[0]
|
31
|
-
values = row[1..]
|
31
|
+
values = row[1..] || []
|
32
32
|
|
33
33
|
new_row = [type_label(type), behavior_name] + values
|
34
34
|
all_rows << new_row
|
@@ -26,7 +26,7 @@ module ClassMetrix
|
|
26
26
|
# Common options for all formatters
|
27
27
|
title: nil,
|
28
28
|
show_metadata: true,
|
29
|
-
extraction_types: []
|
29
|
+
extraction_types: [] # : Array[Symbol]
|
30
30
|
}
|
31
31
|
end
|
32
32
|
|
@@ -52,11 +52,11 @@ module ClassMetrix
|
|
52
52
|
|
53
53
|
def collect_all_hash_keys(rows, _headers)
|
54
54
|
value_start_idx = value_start_index
|
55
|
-
all_keys = {} # behavior_name => Set of keys
|
55
|
+
all_keys = {} # : Hash[String, Set[String]] # behavior_name => Set of keys
|
56
56
|
|
57
57
|
rows.each do |row|
|
58
58
|
behavior_name = row[behavior_column_index]
|
59
|
-
values = row[value_start_idx..]
|
59
|
+
values = row[value_start_idx..] || []
|
60
60
|
|
61
61
|
values.each do |value|
|
62
62
|
if value.is_a?(Hash)
|
@@ -16,7 +16,7 @@ module ClassMetrix
|
|
16
16
|
def generate
|
17
17
|
return [] unless @show_footer
|
18
18
|
|
19
|
-
output = []
|
19
|
+
output = [] # : Array[String]
|
20
20
|
|
21
21
|
# Add separator line
|
22
22
|
output << "---" if @show_separator
|
@@ -36,7 +36,7 @@ module ClassMetrix
|
|
36
36
|
private
|
37
37
|
|
38
38
|
def generate_default_footer
|
39
|
-
output = []
|
39
|
+
output = [] # : Array[String]
|
40
40
|
|
41
41
|
output << (@custom_footer || "*Report generated by ClassMetrix gem*")
|
42
42
|
|
@@ -49,7 +49,7 @@ module ClassMetrix
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def generate_detailed_footer
|
52
|
-
output = []
|
52
|
+
output = [] # : Array[String]
|
53
53
|
|
54
54
|
output << "## Report Information"
|
55
55
|
output << ""
|
@@ -30,7 +30,7 @@ module ClassMetrix
|
|
30
30
|
private
|
31
31
|
|
32
32
|
def generate_markdown_header
|
33
|
-
output = []
|
33
|
+
output = [] # : Array[String]
|
34
34
|
|
35
35
|
# Add title
|
36
36
|
if @title
|
@@ -58,7 +58,7 @@ module ClassMetrix
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def generate_csv_header
|
61
|
-
output = []
|
61
|
+
output = [] # : Array[String]
|
62
62
|
comment_char = @options.fetch(:comment_char, "#")
|
63
63
|
|
64
64
|
# Add title as comment
|
@@ -15,7 +15,7 @@ module ClassMetrix
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def generate
|
18
|
-
output = []
|
18
|
+
output = [] # : Array[String]
|
19
19
|
|
20
20
|
# Add title
|
21
21
|
output.concat(generate_title) if @title || @show_metadata
|
@@ -32,7 +32,7 @@ module ClassMetrix
|
|
32
32
|
private
|
33
33
|
|
34
34
|
def generate_title
|
35
|
-
output = []
|
35
|
+
output = [] # : Array[String]
|
36
36
|
|
37
37
|
if @title
|
38
38
|
output << "# #{@title}"
|
@@ -46,7 +46,7 @@ module ClassMetrix
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def generate_classes_section
|
49
|
-
output = []
|
49
|
+
output = [] # : Array[String]
|
50
50
|
|
51
51
|
has_type_column = @data[:headers].first == "Type"
|
52
52
|
class_headers = if has_type_column
|
@@ -66,7 +66,7 @@ module ClassMetrix
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def generate_extraction_info
|
69
|
-
output = []
|
69
|
+
output = [] # : Array[String]
|
70
70
|
|
71
71
|
output << "## Extraction Types"
|
72
72
|
output << ""
|
@@ -9,7 +9,7 @@ module ClassMetrix
|
|
9
9
|
@options = options
|
10
10
|
@show_missing_summary = options.fetch(:show_missing_summary, false)
|
11
11
|
@summary_style = options.fetch(:summary_style, :grouped) # :grouped, :flat, :detailed
|
12
|
-
@missing_behaviors = {}
|
12
|
+
@missing_behaviors = {} # : Hash[String, Hash[String, String]]
|
13
13
|
end
|
14
14
|
|
15
15
|
def generate
|
@@ -30,7 +30,7 @@ module ClassMetrix
|
|
30
30
|
end
|
31
31
|
|
32
32
|
# Initialize missing behaviors tracking with hash to store behavior name and error message
|
33
|
-
class_headers.each { |class_name| @missing_behaviors[class_name] = {} }
|
33
|
+
class_headers.each { |class_name| @missing_behaviors[class_name] = {} } # : Hash[String, Hash[String, String]]
|
34
34
|
|
35
35
|
@data[:rows].each do |row|
|
36
36
|
behavior_name = has_type_column ? row[1] : row[0]
|
@@ -63,7 +63,7 @@ module ClassMetrix
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def generate_grouped_summary
|
66
|
-
output = []
|
66
|
+
output = [] # : Array[String]
|
67
67
|
|
68
68
|
output << "## Missing Behaviors Summary"
|
69
69
|
output << ""
|
@@ -84,12 +84,12 @@ module ClassMetrix
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def generate_flat_summary
|
87
|
-
output = []
|
87
|
+
output = [] # : Array[String]
|
88
88
|
|
89
89
|
output << "## Missing Behaviors"
|
90
90
|
output << ""
|
91
91
|
|
92
|
-
all_missing = []
|
92
|
+
all_missing = [] # : Array[String]
|
93
93
|
@missing_behaviors.each do |class_name, behaviors_hash|
|
94
94
|
behaviors_hash.each do |behavior_name, error_message|
|
95
95
|
all_missing << "- **#{class_name}**: `#{behavior_name}` - #{error_message}"
|
@@ -103,7 +103,7 @@ module ClassMetrix
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def generate_detailed_summary
|
106
|
-
output = []
|
106
|
+
output = [] # : Array[String]
|
107
107
|
|
108
108
|
total_missing = @missing_behaviors.values.map(&:size).sum
|
109
109
|
total_classes = @missing_behaviors.keys.size
|
@@ -114,7 +114,7 @@ module ClassMetrix
|
|
114
114
|
output << ""
|
115
115
|
|
116
116
|
# Group by error type
|
117
|
-
by_error_type = {}
|
117
|
+
by_error_type = {} # : Hash[String, Array[Hash[Symbol, String]]]
|
118
118
|
@missing_behaviors.each do |class_name, behaviors_hash|
|
119
119
|
behaviors_hash.each do |behavior_name, error_message|
|
120
120
|
error_type = error_message.split.first(2).join(" ") # e.g., "🚫 Not", "⚠️ Error:"
|
@@ -16,7 +16,8 @@ module ClassMetrix
|
|
16
16
|
def process_simple_rows(rows)
|
17
17
|
rows.map do |row|
|
18
18
|
processed_row = [row[0]] # Keep the behavior name as-is
|
19
|
-
row[1..]
|
19
|
+
rest_values = row[1..] || []
|
20
|
+
rest_values.each do |value|
|
20
21
|
processed_row << ValueProcessor.process(value)
|
21
22
|
end
|
22
23
|
processed_row
|
@@ -24,7 +25,7 @@ module ClassMetrix
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def process_expanded_rows(rows)
|
27
|
-
expanded_rows = []
|
28
|
+
expanded_rows = [] # : Array[Array[String]]
|
28
29
|
|
29
30
|
rows.each do |row|
|
30
31
|
if @data_extractor.row_has_expandable_hash?(row)
|
@@ -41,9 +42,11 @@ module ClassMetrix
|
|
41
42
|
|
42
43
|
def process_non_hash_row(row)
|
43
44
|
if @data_extractor.has_type_column?
|
44
|
-
|
45
|
+
rest_values = row[2..] || []
|
46
|
+
[row[0], row[1]] + rest_values.map { |value| ValueProcessor.process(value) }
|
45
47
|
else
|
46
|
-
|
48
|
+
rest_values = row[1..] || []
|
49
|
+
[row[0]] + rest_values.map { |value| ValueProcessor.process(value) }
|
47
50
|
end
|
48
51
|
end
|
49
52
|
|
@@ -57,7 +60,7 @@ module ClassMetrix
|
|
57
60
|
end
|
58
61
|
|
59
62
|
def build_expanded_rows(row_data, all_hash_keys, original_row)
|
60
|
-
expanded_rows = []
|
63
|
+
expanded_rows = [] # : Array[Array[String]]
|
61
64
|
|
62
65
|
# Add main row if configured to show
|
63
66
|
expanded_rows << build_main_expanded_row(row_data) if should_show_main_row?
|
@@ -37,7 +37,10 @@ module ClassMetrix
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def row_has_expandable_hash?(row)
|
40
|
-
row[value_start_index..]
|
40
|
+
values = row[value_start_index..] || []
|
41
|
+
return false if values.nil?
|
42
|
+
|
43
|
+
values.any? { |cell| cell.is_a?(Hash) }
|
41
44
|
end
|
42
45
|
|
43
46
|
def collect_hash_keys(values)
|
@@ -11,7 +11,7 @@ module ClassMetrix
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def render_table(headers, rows, column_widths)
|
14
|
-
output = []
|
14
|
+
output = [] # : Array[String]
|
15
15
|
output << build_row(headers, column_widths)
|
16
16
|
output << build_separator(column_widths)
|
17
17
|
|
@@ -19,7 +19,7 @@ module ClassMetrix
|
|
19
19
|
output << build_row(row, column_widths)
|
20
20
|
end
|
21
21
|
|
22
|
-
output
|
22
|
+
output
|
23
23
|
end
|
24
24
|
|
25
25
|
private
|