eager_eye 0.6.0 → 0.8.0
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/CHANGELOG.md +27 -0
- data/README.md +82 -0
- data/lib/eager_eye/auto_fixer.rb +93 -0
- data/lib/eager_eye/cli.rb +71 -24
- data/lib/eager_eye/fixer_registry.rb +22 -0
- data/lib/eager_eye/fixers/base.rb +48 -0
- data/lib/eager_eye/fixers/count_to_size.rb +18 -0
- data/lib/eager_eye/fixers/pluck_to_select.rb +30 -0
- data/lib/eager_eye/rspec/matchers.rb +71 -0
- data/lib/eager_eye/rspec.rb +8 -0
- data/lib/eager_eye/version.rb +1 -1
- data/lib/eager_eye.rb +5 -0
- metadata +8 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 39f1ea38bf95b25a50a9dc854b1727811ffeadaeb5724e99f3e6160b2867dd79
|
|
4
|
+
data.tar.gz: db049f2205a44e3317d891d2c6c2dbda8f716562916bde05e151b97e532181af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bb4e89fa8d8206a556c9ca7d12d33ee0412091aba756abc0d0581b8ca20907898eb0ed74940f75c2afae727ed2825dd65472222edd566d9cfa8a8978969f0d3e
|
|
7
|
+
data.tar.gz: b34651d34df75eafa06175af3f715948995b9a2896910a4e4ec69f9c7464a1f4d7fdbf1efb844e34b50fa2fb9d5a4f55da8089fb0b1b50aef767bff70695e327
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.0] - 2025-12-16
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **RSpec Integration** - RSpec matchers for testing your codebase
|
|
15
|
+
- `pass_eager_eye` matcher for testing files and directories
|
|
16
|
+
- `only` option to run specific detectors
|
|
17
|
+
- `exclude` option to exclude files by glob pattern
|
|
18
|
+
- `max_issues` option for gradual migration (allows up to N issues)
|
|
19
|
+
- `require "eager_eye/rspec"` for easy integration
|
|
20
|
+
- Helpful failure messages with issue details
|
|
21
|
+
|
|
22
|
+
## [0.7.0] - 2025-12-15
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **Auto-fix Suggestions (Experimental)** - Automatic fix capabilities for simple issues
|
|
27
|
+
- `--suggest-fixes` flag to show auto-fix suggestions in diff format
|
|
28
|
+
- `--fix` flag to apply auto-fixes interactively
|
|
29
|
+
- `--fix --force` to apply all fixes without confirmation
|
|
30
|
+
- Fixer for `.count` → `.size` transformation in iterations
|
|
31
|
+
- Fixer for inline `.pluck(:id)` → `.select(:id)` transformation
|
|
32
|
+
|
|
33
|
+
### Note
|
|
34
|
+
|
|
35
|
+
Auto-fix is experimental. Not all issues are auto-fixable. Always review changes and run your test suite after applying fixes.
|
|
36
|
+
|
|
10
37
|
## [0.6.0] - 2025-12-15
|
|
11
38
|
|
|
12
39
|
### Added
|
data/README.md
CHANGED
|
@@ -316,6 +316,88 @@ Both CamelCase and snake_case formats are accepted:
|
|
|
316
316
|
| Pluck to Array | `PluckToArray` | `pluck_to_array` |
|
|
317
317
|
| All Detectors | `all` | `all` |
|
|
318
318
|
|
|
319
|
+
## Auto-fix (Experimental)
|
|
320
|
+
|
|
321
|
+
EagerEye can automatically fix some simple issues:
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
# Show fix suggestions
|
|
325
|
+
eager_eye --suggest-fixes
|
|
326
|
+
|
|
327
|
+
# Apply fixes interactively
|
|
328
|
+
eager_eye --fix
|
|
329
|
+
|
|
330
|
+
# Apply all fixes without confirmation
|
|
331
|
+
eager_eye --fix --force
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Currently Supported Auto-fixes
|
|
335
|
+
|
|
336
|
+
| Issue | Fix |
|
|
337
|
+
|-------|-----|
|
|
338
|
+
| `.count` in iteration | → `.size` |
|
|
339
|
+
| `.pluck(:id)` inline | → `.select(:id)` |
|
|
340
|
+
|
|
341
|
+
### Example
|
|
342
|
+
|
|
343
|
+
```
|
|
344
|
+
$ eager_eye --suggest-fixes
|
|
345
|
+
|
|
346
|
+
app/controllers/posts_controller.rb:
|
|
347
|
+
Line 15:
|
|
348
|
+
- user.posts.count
|
|
349
|
+
+ user.posts.size
|
|
350
|
+
|
|
351
|
+
$ eager_eye --fix
|
|
352
|
+
app/controllers/posts_controller.rb:15
|
|
353
|
+
- user.posts.count
|
|
354
|
+
+ user.posts.size
|
|
355
|
+
Apply this fix? [y/n/q] y
|
|
356
|
+
Applied
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
> **Warning:** Auto-fix is experimental. Always review changes and run your test suite after applying fixes.
|
|
360
|
+
|
|
361
|
+
## RSpec Integration
|
|
362
|
+
|
|
363
|
+
EagerEye provides RSpec matchers for testing your codebase:
|
|
364
|
+
|
|
365
|
+
```ruby
|
|
366
|
+
# spec/rails_helper.rb
|
|
367
|
+
require "eager_eye/rspec"
|
|
368
|
+
|
|
369
|
+
# spec/eager_eye_spec.rb
|
|
370
|
+
RSpec.describe "EagerEye Analysis" do
|
|
371
|
+
it "controllers have no N+1 issues" do
|
|
372
|
+
expect("app/controllers").to pass_eager_eye
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
it "serializers are clean" do
|
|
376
|
+
expect("app/serializers").to pass_eager_eye(only: [:serializer_nesting])
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# Allow some issues during migration
|
|
380
|
+
it "legacy code is acceptable" do
|
|
381
|
+
expect("app/services/legacy").to pass_eager_eye(max_issues: 10)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
it "models have no callback issues except legacy" do
|
|
385
|
+
expect("app/models").to pass_eager_eye(
|
|
386
|
+
only: [:callback_query],
|
|
387
|
+
exclude: ["app/models/legacy/**"]
|
|
388
|
+
)
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Matcher Options
|
|
394
|
+
|
|
395
|
+
| Option | Type | Description |
|
|
396
|
+
|--------|------|-------------|
|
|
397
|
+
| `only` | `Array<Symbol>` | Run only specified detectors |
|
|
398
|
+
| `exclude` | `Array<String>` | Glob patterns to exclude |
|
|
399
|
+
| `max_issues` | `Integer` | Maximum allowed issues (default: 0) |
|
|
400
|
+
|
|
319
401
|
## Configuration
|
|
320
402
|
|
|
321
403
|
### Config File (.eager_eye.yml)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EagerEye
|
|
4
|
+
class AutoFixer
|
|
5
|
+
def initialize(issues, interactive: true)
|
|
6
|
+
@issues = issues
|
|
7
|
+
@interactive = interactive
|
|
8
|
+
@files_cache = {}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def run
|
|
12
|
+
fixes = collect_fixes
|
|
13
|
+
return puts "No auto-fixable issues found." if fixes.empty?
|
|
14
|
+
|
|
15
|
+
if @interactive
|
|
16
|
+
apply_interactively(fixes)
|
|
17
|
+
else
|
|
18
|
+
apply_all(fixes)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def suggest
|
|
23
|
+
fixes = collect_fixes
|
|
24
|
+
return puts "No auto-fixable issues found." if fixes.empty?
|
|
25
|
+
|
|
26
|
+
fixes.group_by { |f| f[:file] }.each do |file, file_fixes|
|
|
27
|
+
puts "\n#{file}:"
|
|
28
|
+
file_fixes.each do |fix|
|
|
29
|
+
puts " Line #{fix[:line]}:"
|
|
30
|
+
puts " - #{fix[:original]}"
|
|
31
|
+
puts " + #{fix[:fixed]}"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def collect_fixes
|
|
39
|
+
@issues.filter_map do |issue|
|
|
40
|
+
source = read_file(issue.file_path)
|
|
41
|
+
fixer = FixerRegistry.fixer_for(issue, source)
|
|
42
|
+
next unless fixer&.fixable?
|
|
43
|
+
|
|
44
|
+
fixer.diff
|
|
45
|
+
end.compact
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def read_file(path)
|
|
49
|
+
@files_cache[path] ||= File.read(path)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def apply_interactively(fixes)
|
|
53
|
+
fixes.each do |fix|
|
|
54
|
+
puts "\n#{fix[:file]}:#{fix[:line]}"
|
|
55
|
+
puts " - #{fix[:original]}"
|
|
56
|
+
puts " + #{fix[:fixed]}"
|
|
57
|
+
print "Apply this fix? [y/n/q] "
|
|
58
|
+
|
|
59
|
+
response = $stdin.gets&.chomp&.downcase
|
|
60
|
+
case response
|
|
61
|
+
when "y"
|
|
62
|
+
apply_fix(fix)
|
|
63
|
+
puts " Applied"
|
|
64
|
+
when "q"
|
|
65
|
+
puts "Aborted."
|
|
66
|
+
break
|
|
67
|
+
else
|
|
68
|
+
puts " Skipped"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def apply_all(fixes)
|
|
74
|
+
# Group by file to minimize file operations
|
|
75
|
+
fixes.group_by { |f| f[:file] }.each do |file, file_fixes|
|
|
76
|
+
lines = File.readlines(file)
|
|
77
|
+
|
|
78
|
+
file_fixes.sort_by { |f| -f[:line] }.each do |fix|
|
|
79
|
+
lines[fix[:line] - 1] = "#{fix[:fixed]}\n"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
File.write(file, lines.join)
|
|
83
|
+
puts "Fixed #{file_fixes.size} issue(s) in #{file}"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def apply_fix(fix)
|
|
88
|
+
lines = File.readlines(fix[:file])
|
|
89
|
+
lines[fix[:line] - 1] = "#{fix[:fixed]}\n"
|
|
90
|
+
File.write(fix[:file], lines.join)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
data/lib/eager_eye/cli.rb
CHANGED
|
@@ -16,6 +16,19 @@ module EagerEye
|
|
|
16
16
|
return 0 if options[:help] || options[:version]
|
|
17
17
|
|
|
18
18
|
issues = analyze
|
|
19
|
+
|
|
20
|
+
if options[:suggest_fixes]
|
|
21
|
+
fixer = AutoFixer.new(issues)
|
|
22
|
+
fixer.suggest
|
|
23
|
+
return 0
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if options[:fix]
|
|
27
|
+
fixer = AutoFixer.new(issues, interactive: !options[:force])
|
|
28
|
+
fixer.run
|
|
29
|
+
return 0
|
|
30
|
+
end
|
|
31
|
+
|
|
19
32
|
output_report(issues)
|
|
20
33
|
exit_code(issues)
|
|
21
34
|
end
|
|
@@ -31,7 +44,10 @@ module EagerEye
|
|
|
31
44
|
fail_on_issues: true,
|
|
32
45
|
colorize: $stdout.tty?,
|
|
33
46
|
help: false,
|
|
34
|
-
version: false
|
|
47
|
+
version: false,
|
|
48
|
+
suggest_fixes: false,
|
|
49
|
+
fix: false,
|
|
50
|
+
force: false
|
|
35
51
|
}
|
|
36
52
|
end
|
|
37
53
|
|
|
@@ -50,35 +66,66 @@ module EagerEye
|
|
|
50
66
|
opts.separator ""
|
|
51
67
|
opts.separator "Options:"
|
|
52
68
|
|
|
53
|
-
opts
|
|
54
|
-
|
|
55
|
-
|
|
69
|
+
add_output_options(opts)
|
|
70
|
+
add_filter_options(opts)
|
|
71
|
+
add_behavior_options(opts)
|
|
72
|
+
add_info_options(opts)
|
|
73
|
+
add_fix_options(opts)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
56
76
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
77
|
+
def add_output_options(opts)
|
|
78
|
+
opts.on("-f", "--format FORMAT", %i[console json], "Output format (console, json)") do |format|
|
|
79
|
+
options[:format] = format
|
|
80
|
+
end
|
|
60
81
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
82
|
+
opts.on("--no-color", "Disable colored output") do
|
|
83
|
+
options[:colorize] = false
|
|
84
|
+
end
|
|
85
|
+
end
|
|
64
86
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
87
|
+
def add_filter_options(opts)
|
|
88
|
+
opts.on("-e", "--exclude PATTERN", "Exclude files matching pattern") do |pattern|
|
|
89
|
+
options[:exclude] << pattern
|
|
90
|
+
end
|
|
68
91
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
92
|
+
opts.on("-o", "--only DETECTORS", "Run only specified detectors (comma-separated)") do |detectors|
|
|
93
|
+
options[:only] = detectors.split(",").map(&:strip).map(&:to_sym)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
72
96
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
97
|
+
def add_behavior_options(opts)
|
|
98
|
+
opts.on("--no-fail", "Exit with 0 even if issues found") do
|
|
99
|
+
options[:fail_on_issues] = false
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def add_info_options(opts)
|
|
104
|
+
opts.on("-v", "--version", "Show version") do
|
|
105
|
+
puts "EagerEye #{EagerEye::VERSION}"
|
|
106
|
+
options[:version] = true
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
opts.on("-h", "--help", "Show this help message") do
|
|
110
|
+
puts opts
|
|
111
|
+
options[:help] = true
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def add_fix_options(opts)
|
|
116
|
+
opts.separator ""
|
|
117
|
+
opts.separator "Auto-fix options (experimental):"
|
|
118
|
+
|
|
119
|
+
opts.on("--suggest-fixes", "Show auto-fix suggestions") do
|
|
120
|
+
options[:suggest_fixes] = true
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
opts.on("--fix", "Apply auto-fixes interactively") do
|
|
124
|
+
options[:fix] = true
|
|
125
|
+
end
|
|
77
126
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
options[:help] = true
|
|
81
|
-
end
|
|
127
|
+
opts.on("--force", "Apply fixes without confirmation (use with --fix)") do
|
|
128
|
+
options[:force] = true
|
|
82
129
|
end
|
|
83
130
|
end
|
|
84
131
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EagerEye
|
|
4
|
+
class FixerRegistry
|
|
5
|
+
FIXERS = {
|
|
6
|
+
count_in_iteration: Fixers::CountToSize,
|
|
7
|
+
pluck_to_array: Fixers::PluckToSelect
|
|
8
|
+
}.freeze
|
|
9
|
+
|
|
10
|
+
def self.fixer_for(issue, source_code)
|
|
11
|
+
fixer_class = FIXERS[issue.detector]
|
|
12
|
+
return nil unless fixer_class
|
|
13
|
+
|
|
14
|
+
fixer_class.new(issue, source_code)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.fixable?(issue, source_code)
|
|
18
|
+
fixer = fixer_for(issue, source_code)
|
|
19
|
+
fixer&.fixable? || false
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EagerEye
|
|
4
|
+
module Fixers
|
|
5
|
+
class Base
|
|
6
|
+
attr_reader :issue, :source_lines
|
|
7
|
+
|
|
8
|
+
def initialize(issue, source_code)
|
|
9
|
+
@issue = issue
|
|
10
|
+
@source_code = source_code
|
|
11
|
+
@source_lines = source_code.lines
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def fixable?
|
|
15
|
+
false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def fix
|
|
19
|
+
raise NotImplementedError
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def diff
|
|
23
|
+
return nil unless fixable?
|
|
24
|
+
|
|
25
|
+
original_line = @source_lines[issue.line_number - 1]
|
|
26
|
+
fixed_line = fixed_content
|
|
27
|
+
return nil if original_line == fixed_line
|
|
28
|
+
|
|
29
|
+
{
|
|
30
|
+
file: issue.file_path,
|
|
31
|
+
line: issue.line_number,
|
|
32
|
+
original: original_line.chomp,
|
|
33
|
+
fixed: fixed_line.chomp
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
protected
|
|
38
|
+
|
|
39
|
+
def fixed_content
|
|
40
|
+
raise NotImplementedError
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def line_content
|
|
44
|
+
@source_lines[issue.line_number - 1]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EagerEye
|
|
4
|
+
module Fixers
|
|
5
|
+
class CountToSize < Base
|
|
6
|
+
def fixable?
|
|
7
|
+
issue.detector == :count_in_iteration &&
|
|
8
|
+
line_content&.include?(".count")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
protected
|
|
12
|
+
|
|
13
|
+
def fixed_content
|
|
14
|
+
line_content.gsub(/\.count\b/, ".size")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EagerEye
|
|
4
|
+
module Fixers
|
|
5
|
+
class PluckToSelect < Base
|
|
6
|
+
# This fixer only works for single-line pluck + where patterns
|
|
7
|
+
# Two-line patterns are too complex to fix automatically
|
|
8
|
+
|
|
9
|
+
def fixable?
|
|
10
|
+
issue.detector == :pluck_to_array &&
|
|
11
|
+
single_line_pattern?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
protected
|
|
15
|
+
|
|
16
|
+
def fixed_content
|
|
17
|
+
# Model.where(col: OtherModel.pluck(:id)) -> Model.where(col: OtherModel.select(:id))
|
|
18
|
+
line_content.gsub(/\.pluck\((:\w+)\)/, '.select(\1)')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def single_line_pattern?
|
|
24
|
+
return false unless line_content
|
|
25
|
+
|
|
26
|
+
line_content.include?(".pluck(") && line_content.include?(".where(")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module EagerEye
|
|
4
|
+
module RSpec
|
|
5
|
+
module Matchers
|
|
6
|
+
def pass_eager_eye(options = {})
|
|
7
|
+
PassEagerEyeMatcher.new(options)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class PassEagerEyeMatcher
|
|
11
|
+
def initialize(options = {})
|
|
12
|
+
@only = options[:only]
|
|
13
|
+
@exclude = options[:exclude] || []
|
|
14
|
+
@max_issues = options[:max_issues] || 0
|
|
15
|
+
@issues = []
|
|
16
|
+
@path = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def matches?(path)
|
|
20
|
+
@path = path
|
|
21
|
+
configure_eager_eye
|
|
22
|
+
analyzer = build_analyzer
|
|
23
|
+
@issues = analyzer.run
|
|
24
|
+
@issues.count <= @max_issues
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def failure_message
|
|
28
|
+
message = "expected #{@path} to pass EagerEye analysis"
|
|
29
|
+
message += " (max #{@max_issues} issues)" if @max_issues.positive?
|
|
30
|
+
message += ", but found #{@issues.count} issue(s):\n\n"
|
|
31
|
+
|
|
32
|
+
@issues.group_by(&:file_path).each do |file, file_issues|
|
|
33
|
+
message += "#{file}:\n"
|
|
34
|
+
file_issues.each do |issue|
|
|
35
|
+
message += " Line #{issue.line_number}: [#{issue.detector}] #{issue.message}\n"
|
|
36
|
+
end
|
|
37
|
+
message += "\n"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
message
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def failure_message_when_negated
|
|
44
|
+
"expected #{@path} to have EagerEye issues, but it passed"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def description
|
|
48
|
+
desc = "pass EagerEye analysis"
|
|
49
|
+
desc += " for #{@only.join(", ")}" if @only
|
|
50
|
+
desc += " (max #{@max_issues} issues)" if @max_issues.positive?
|
|
51
|
+
desc
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def configure_eager_eye
|
|
57
|
+
EagerEye.reset_configuration!
|
|
58
|
+
EagerEye.configure do |config|
|
|
59
|
+
config.enabled_detectors = @only if @only
|
|
60
|
+
config.excluded_paths = @exclude unless @exclude.empty?
|
|
61
|
+
config.fail_on_issues = false
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def build_analyzer
|
|
66
|
+
EagerEye::Analyzer.new(paths: [@path])
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
data/lib/eager_eye/version.rb
CHANGED
data/lib/eager_eye.rb
CHANGED
|
@@ -13,6 +13,11 @@ require_relative "eager_eye/detectors/callback_query"
|
|
|
13
13
|
require_relative "eager_eye/detectors/pluck_to_array"
|
|
14
14
|
require_relative "eager_eye/comment_parser"
|
|
15
15
|
require_relative "eager_eye/analyzer"
|
|
16
|
+
require_relative "eager_eye/fixers/base"
|
|
17
|
+
require_relative "eager_eye/fixers/count_to_size"
|
|
18
|
+
require_relative "eager_eye/fixers/pluck_to_select"
|
|
19
|
+
require_relative "eager_eye/fixer_registry"
|
|
20
|
+
require_relative "eager_eye/auto_fixer"
|
|
16
21
|
require_relative "eager_eye/reporters/base"
|
|
17
22
|
require_relative "eager_eye/reporters/console"
|
|
18
23
|
require_relative "eager_eye/reporters/json"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: eager_eye
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- hamzagedikkaya
|
|
@@ -58,6 +58,7 @@ files:
|
|
|
58
58
|
- exe/eager_eye
|
|
59
59
|
- lib/eager_eye.rb
|
|
60
60
|
- lib/eager_eye/analyzer.rb
|
|
61
|
+
- lib/eager_eye/auto_fixer.rb
|
|
61
62
|
- lib/eager_eye/cli.rb
|
|
62
63
|
- lib/eager_eye/comment_parser.rb
|
|
63
64
|
- lib/eager_eye/configuration.rb
|
|
@@ -69,12 +70,18 @@ files:
|
|
|
69
70
|
- lib/eager_eye/detectors/missing_counter_cache.rb
|
|
70
71
|
- lib/eager_eye/detectors/pluck_to_array.rb
|
|
71
72
|
- lib/eager_eye/detectors/serializer_nesting.rb
|
|
73
|
+
- lib/eager_eye/fixer_registry.rb
|
|
74
|
+
- lib/eager_eye/fixers/base.rb
|
|
75
|
+
- lib/eager_eye/fixers/count_to_size.rb
|
|
76
|
+
- lib/eager_eye/fixers/pluck_to_select.rb
|
|
72
77
|
- lib/eager_eye/generators/install_generator.rb
|
|
73
78
|
- lib/eager_eye/issue.rb
|
|
74
79
|
- lib/eager_eye/railtie.rb
|
|
75
80
|
- lib/eager_eye/reporters/base.rb
|
|
76
81
|
- lib/eager_eye/reporters/console.rb
|
|
77
82
|
- lib/eager_eye/reporters/json.rb
|
|
83
|
+
- lib/eager_eye/rspec.rb
|
|
84
|
+
- lib/eager_eye/rspec/matchers.rb
|
|
78
85
|
- lib/eager_eye/version.rb
|
|
79
86
|
- sig/eager_eye.rbs
|
|
80
87
|
homepage: https://github.com/hamzagedikkaya/eager_eye
|