eager_eye 1.0.8 → 1.0.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b2e83de186394077d36507bd9c14dbb356777bddff49689c602b43dc8d74b80
4
- data.tar.gz: 5ee79306b8bd9f602e9f09ed1c62bf5adb5920d57104c486d8799a757458eb6f
3
+ metadata.gz: 44b2f46a77bcc0bb742c6d169cebb7be6b9a8b722b64044b153397fcf7686872
4
+ data.tar.gz: 25a589c3401fe25248b6fe429e0255e5d2d9ada9b50bd7bbf467ada161e0ca95
5
5
  SHA512:
6
- metadata.gz: 36d9dabec10f32dcf21c88efdd5125e5f7146cf61e0e500adc4f3c5b57608303cf0002d7ac48c32eb87b8f163fa6c3125d53bce4e052e9c1dd178f244b69e2a3
7
- data.tar.gz: 6bc77a99dd29179c9179010ff1c6bb195048115b3b72e545ec51d1af1d286a430a35b223a138fc78e66dbb0172d9e2ff2f39c9f9639be9edc97a47eb928e3df6
6
+ metadata.gz: 2ea1baa8c98a5362527e991d3712c0a3c0d821307a99e1b8b1a9a0ac76fbff5d4adcf4f4cd512990971956fcc3bd61ef97fb8c047d0b44609e4bd55ca385bfb4
7
+ data.tar.gz: 8d1590b243420e3ea3534290f15725a0aa70f3ea537aa7da05cd4648521fe284718965d27e4b00ac77ea277d4ca400107e49a18a7759780dd532c560ef1b91b3
data/CHANGELOG.md CHANGED
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.0.9] - 2025-12-26
11
+
12
+ ### Added
13
+
14
+ - **Inline Suppression Comments** - Suppress specific warnings with RuboCop-style inline comments
15
+ - `# eager_eye:disable-next-line` - Suppress next line
16
+ - `# eager_eye:disable CallbackQuery` - Suppress specific detector inline
17
+ - `# eager_eye:disable-block` / `# eager_eye:enable-block` - Suppress block of code
18
+ - `# eager_eye:disable-file DetectorName` - Suppress entire file
19
+ - Supports both CamelCase and snake_case detector names
20
+ - Can disable all detectors with `all` keyword
21
+
22
+ ### Improved
23
+
24
+ - Enhanced README with table of contents and better organization
25
+ - Improved code readability and documentation structure
26
+ - Updated version badge to v1.0.9
27
+
10
28
  ## [1.0.8] - 2025-12-25
11
29
 
12
30
  ### Added
data/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  <p align="center">
12
12
  <a href="https://github.com/hamzagedikkaya/eager_eye/actions/workflows/main.yml"><img src="https://github.com/hamzagedikkaya/eager_eye/actions/workflows/main.yml/badge.svg" alt="CI"></a>
13
- <a href="https://rubygems.org/gems/eager_eye"><img src="https://img.shields.io/badge/gem-v1.0.8-red.svg" alt="Gem Version"></a>
13
+ <a href="https://rubygems.org/gems/eager_eye"><img src="https://img.shields.io/badge/gem-v1.0.9-red.svg" alt="Gem Version"></a>
14
14
  <a href="https://github.com/hamzagedikkaya/eager_eye"><img src="https://img.shields.io/badge/coverage-95%25-brightgreen.svg" alt="Coverage"></a>
15
15
  <a href="https://www.ruby-lang.org/"><img src="https://img.shields.io/badge/ruby-%3E%3D%203.1-ruby.svg" alt="Ruby"></a>
16
16
  <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
@@ -23,6 +23,24 @@
23
23
 
24
24
  ---
25
25
 
26
+ ## Table of Contents
27
+ - [Why EagerEye?](#why-eagereye)
28
+ - [Features](#features)
29
+ - [Installation](#installation)
30
+ - [Quick Start](#quick-start)
31
+ - [Detected Issues](#detected-issues)
32
+ - [Inline Suppression](#inline-suppression)
33
+ - [Auto-fix](#auto-fix-experimental)
34
+ - [RSpec Integration](#rspec-integration)
35
+ - [Configuration](#configuration)
36
+ - [CI Integration](#ci-integration)
37
+ - [CLI Reference](#cli-reference)
38
+ - [Output Formats](#output-formats)
39
+ - [Limitations](#limitations)
40
+ - [VS Code Extension](#vs-code-extension)
41
+ - [Development](#development)
42
+ - [Contributing](#contributing)
43
+
26
44
  ## Why EagerEye?
27
45
 
28
46
  Unlike runtime tools like Bullet, EagerEye:
@@ -41,6 +59,28 @@ Unlike runtime tools like Bullet, EagerEye:
41
59
  | CI integration | Native | Requires tests |
42
60
  | False positive rate | Higher | Lower |
43
61
 
62
+ ## Features
63
+
64
+ ✨ **Detects 7 types of N+1 problems:**
65
+ - Loop associations (queries in iterations)
66
+ - Serializer nesting issues
67
+ - Missing counter caches
68
+ - Custom method queries (invisible to Bullet)
69
+ - Count in iteration patterns
70
+ - Callback query N+1s
71
+ - Pluck to array misuse
72
+
73
+ 🔧 **Developer-friendly:**
74
+ - Inline suppression (like RuboCop)
75
+ - Auto-fix support (experimental)
76
+ - JSON/Console output formats
77
+ - RSpec integration
78
+
79
+ 🚀 **CI-ready:**
80
+ - No test suite required
81
+ - GitHub Actions examples included
82
+ - Severity levels and filtering
83
+
44
84
  ## Installation
45
85
 
46
86
  Add to your Gemfile:
@@ -2,12 +2,12 @@
2
2
 
3
3
  module EagerEye
4
4
  class CommentParser
5
- DISABLE_PATTERN = /eager_eye:disable(?:-next-line|-file)?\s+(.+?)(?:\s+--|$)/i
6
- ENABLE_PATTERN = /eager_eye:enable\s+(.+?)(?:\s+--|$)/i
7
- INLINE_DISABLE_PATTERN = /eager_eye:disable\s+(.+?)(?:\s+--|$)/i
8
5
  FILE_DISABLE_PATTERN = /eager_eye:disable-file\s+(.+?)(?:\s+--|$)/i
9
- NEXT_LINE_PATTERN = /eager_eye:disable-next-line\s+(.+?)(?:\s+--|$)/i
10
- BLOCK_DISABLE_PATTERN = /eager_eye:disable\s+(.+?)(?:\s+--|$)/i
6
+ NEXT_LINE_PATTERN = /eager_eye:disable-next-line(?:\s+(.+?))?(?:\s+--|$)/i
7
+ BLOCK_START_PATTERN = /eager_eye:disable-block(?:\s+(.+?))?(?:\s+--|$)/i
8
+ BLOCK_END_PATTERN = /eager_eye:enable-block(?:\s+(.+?))?(?:\s+--|$)/i
9
+ INLINE_DISABLE_PATTERN = /eager_eye:disable\s+(.+?)(?:\s+--|$)/i
10
+ ENABLE_PATTERN = /eager_eye:enable(?:\s+(.+?))?(?:\s+--|$)/i
11
11
 
12
12
  def initialize(source_code)
13
13
  @source_code = source_code.encode("UTF-8", invalid: :replace, undef: :replace)
@@ -46,39 +46,50 @@ module EagerEye
46
46
  def detect_directive(line, line_num)
47
47
  detect_file_directive(line, line_num) ||
48
48
  detect_next_line_directive(line) ||
49
- detect_block_directive(line) ||
50
- detect_enable_directive(line) ||
51
- detect_inline_directive(line)
49
+ detect_block_end_directive(line) ||
50
+ detect_block_or_inline_directive(line)
52
51
  end
53
52
 
54
53
  def detect_file_directive(line, line_num)
55
54
  return unless line_num <= 5 && line =~ FILE_DISABLE_PATTERN
56
55
 
57
- { type: :file, detectors: parse_detector_names(::Regexp.last_match(1)) }
56
+ detectors = parse_detector_names(::Regexp.last_match(1) || "all")
57
+ { type: :file, detectors: detectors }
58
58
  end
59
59
 
60
60
  def detect_next_line_directive(line)
61
61
  return unless line =~ NEXT_LINE_PATTERN
62
62
 
63
- { type: :next_line, detectors: parse_detector_names(::Regexp.last_match(1)) }
63
+ detectors = parse_detector_names(::Regexp.last_match(1) || "all")
64
+ { type: :next_line, detectors: detectors }
64
65
  end
65
66
 
66
- def detect_block_directive(line)
67
- return unless line =~ BLOCK_DISABLE_PATTERN && !inline_disable?(line)
68
-
69
- { type: :block_start, detectors: parse_detector_names(::Regexp.last_match(1)) }
70
- end
71
-
72
- def detect_enable_directive(line)
67
+ def detect_block_end_directive(line)
73
68
  return unless line =~ ENABLE_PATTERN
74
69
 
75
- { type: :block_end, detectors: parse_detector_names(::Regexp.last_match(1)) }
70
+ detectors = parse_detector_names(::Regexp.last_match(1) || "all")
71
+ { type: :block_end, detectors: detectors }
76
72
  end
77
73
 
78
- def detect_inline_directive(line)
74
+ def detect_block_or_inline_directive(line)
75
+ # Check for eager_eye:disable-block explicitly
76
+ if line =~ BLOCK_START_PATTERN && !code_before_comment?(line)
77
+ detectors = parse_detector_names(::Regexp.last_match(1) || "all")
78
+ return { type: :block_start, detectors: detectors }
79
+ end
80
+
81
+ # Check for eager_eye:disable (either inline or block start)
79
82
  return unless line =~ INLINE_DISABLE_PATTERN
80
83
 
81
- { type: :inline, detectors: parse_detector_names(::Regexp.last_match(1)) }
84
+ detectors = parse_detector_names(::Regexp.last_match(1) || "all")
85
+
86
+ # If there's code before the comment, it's inline (same line only)
87
+ if code_before_comment?(line)
88
+ { type: :inline, detectors: detectors }
89
+ else
90
+ # No code before comment, so it's a block start
91
+ { type: :block_start, detectors: detectors }
92
+ end
82
93
  end
83
94
 
84
95
  def apply_directive(directive, line_num)
@@ -129,7 +140,14 @@ module EagerEye
129
140
  code_part && !code_part.strip.empty?
130
141
  end
131
142
 
143
+ def code_before_comment?(line)
144
+ code_part = line.split("#").first
145
+ code_part && !code_part.strip.empty?
146
+ end
147
+
132
148
  def parse_detector_names(str)
149
+ return ["all"] if str.nil? || str.strip.empty?
150
+
133
151
  str.split(/[,\s]+/).map(&:strip).reject(&:empty?).map do |name|
134
152
  normalize_detector_name(name)
135
153
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EagerEye
4
- VERSION = "1.0.8"
4
+ VERSION = "1.0.9"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eager_eye
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.8
4
+ version: 1.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - hamzagedikkaya
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-12-25 00:00:00.000000000 Z
11
+ date: 2025-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ast