eager_eye 1.1.9 → 1.1.11

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: e5affda3dbf4ab9e59ce8c0a5fcbadd3b6b11bf60eba882031226050589a2a04
4
- data.tar.gz: bfa17f748016257d75c7135908656c9bf920b3dc0ea6d8fbbd41352b8a3c96f4
3
+ metadata.gz: 200f52cfc9b2d47ee338155372eded81c115c5c05578e6ff89e689f148fabac5
4
+ data.tar.gz: 3b236fff4d78662c30140b3e429d222defed03100b2c8d6928711886bd7c525a
5
5
  SHA512:
6
- metadata.gz: e2d0edc257c6384c294a6f3a40037e2841c9c4a7d0f07cce69cf144ee01cf46353ec58d8db13da9549604206460d43efa4da91fb0966961a827e59cb3fe2518b
7
- data.tar.gz: 665ba27b30fda25e287ecc7ac34d573d8f523ed1eaab9f52fb9f628ce74b0a562e57a3a92bd6ef70226b9ccadb825577ae7d21e7f674fe080dac01f1df463dbe
6
+ metadata.gz: 8a09fbc10c6f944c9c42f31723dc0bf248eff29691a35fbc31f6a4e21836224225863eb625ac33e818a30b2e12b119831e02ec2f0d0689476e014a9ab0d5331e
7
+ data.tar.gz: 36dff575a0277abc141848a1866a057f31fcefe6fdecd861a32fcad7120167a56120f0ed8a507c9ff9fdcb4ac54be72be64a475ca0b5105574ace91e26618f8b
data/CHANGELOG.md CHANGED
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.1.11] - 2026-01-13
11
+
12
+ ### Fixed
13
+
14
+ - **CustomMethodQuery False Positive** - Skip `count`, `sum`, `find` on safe collections
15
+ - `id.to_s.count` no longer flagged (scalar count)
16
+ - `array.count` no longer flagged inside iteration
17
+ - Expanded safe transform methods (`to_s`, `to_i`, `to_a`, `chars`, `bytes`)
18
+
19
+ ## [1.1.10] - 2026-01-12
20
+
21
+ ### Fixed
22
+
23
+ - **CustomMethodQuery False Positive** - Skip `pluck` and `ids` results
24
+ - `Model.pluck(:id).each { |id| ... }` no longer flagged
25
+ - Supports tracking local variable assignments for pluck results
26
+
10
27
  ## [1.1.9] - 2026-01-11
11
28
 
12
29
  ### Fixed
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.1.9-red.svg" alt="Gem Version"></a>
13
+ <a href="https://rubygems.org/gems/eager_eye"><img src="https://img.shields.io/badge/gem-v1.1.11-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>
@@ -5,10 +5,8 @@ module EagerEye
5
5
  class CustomMethodQuery < Base
6
6
  QUERY_METHODS = %i[where find_by find_by! exists? find first last take pluck ids count sum average minimum
7
7
  maximum].freeze
8
- ARRAY_METHODS = %i[first last take].freeze
9
- HASH_ARRAY_METHODS = %i[keys values].freeze
10
- STRING_ARRAY_METHODS = %i[split].freeze
11
- BRACKET_ARRAY_METHODS = %i[[]].freeze
8
+ SAFE_QUERY_METHODS = %i[first last take count sum find size length].freeze
9
+ SAFE_TRANSFORM_METHODS = %i[keys values split [] params sort pluck ids to_s to_a to_i chars bytes].freeze
12
10
  ITERATION_METHODS = %i[each map select find_all reject collect detect find_index flat_map].freeze
13
11
 
14
12
  def self.detector_name
@@ -21,8 +19,8 @@ module EagerEye
21
19
  @issues = []
22
20
  @file_path = file_path
23
21
 
24
- find_iteration_blocks(ast) do |block_body, block_var, collection|
25
- is_array_collection = collection_is_array?(collection)
22
+ find_iteration_blocks(ast) do |block_body, block_var, collection, definitions|
23
+ is_array_collection = collection_is_array?(collection, definitions)
26
24
  check_block_for_query_methods(block_body, block_var, is_array_collection)
27
25
  end
28
26
 
@@ -31,15 +29,17 @@ module EagerEye
31
29
 
32
30
  private
33
31
 
34
- def find_iteration_blocks(node, &block)
32
+ def find_iteration_blocks(node, definitions = {}, &block)
35
33
  return unless node.is_a?(Parser::AST::Node)
36
34
 
35
+ definitions[node.children[0]] = node.children[1] if node.type == :lvasgn
36
+
37
37
  if iteration_block?(node)
38
38
  block_var = extract_block_variable(node)
39
39
  block_body = node.children[2]
40
- yield(block_body, block_var, node.children[0]) if block_var && block_body
40
+ yield(block_body, block_var, node.children[0], definitions) if block_var && block_body
41
41
  end
42
- node.children.each { |child| find_iteration_blocks(child, &block) }
42
+ node.children.each { |child| find_iteration_blocks(child, definitions, &block) }
43
43
  end
44
44
 
45
45
  def iteration_block?(node)
@@ -65,9 +65,9 @@ module EagerEye
65
65
  end
66
66
 
67
67
  def skip_array_method?(node, block_var, is_array_collection)
68
- return true if receiver_ends_with_hash_array_method?(node.children[0])
68
+ return true if receiver_ends_with_safe_transform_method?(node.children[0])
69
69
 
70
- ARRAY_METHODS.include?(node.children[1]) &&
70
+ SAFE_QUERY_METHODS.include?(node.children[1]) &&
71
71
  is_array_collection && receiver_is_only_block_var?(node.children[0], block_var)
72
72
  end
73
73
 
@@ -93,28 +93,34 @@ module EagerEye
93
93
  first_arg&.type == :arg ? first_arg.children[0] : nil
94
94
  end
95
95
 
96
- def collection_is_array?(node)
96
+ def collection_is_array?(node, definitions = {})
97
97
  return false unless node.is_a?(Parser::AST::Node)
98
-
99
98
  return true if %i[array hash].include?(node.type)
99
+ return check_lvar_collection?(node, definitions) if node.type == :lvar
100
+ return check_send_collection?(node, definitions) if node.type == :send
100
101
 
101
- if node.type == :send
102
- method_name = node.children[1]
103
- return true if %i[map select collect flat_map to_a uniq compact keys values split []
104
- params sort].include?(method_name)
102
+ false
103
+ end
105
104
 
106
- return collection_is_array?(node.children[0])
107
- end
105
+ def check_lvar_collection?(node, definitions)
106
+ return false unless definitions
108
107
 
109
- false
108
+ definition = definitions[node.children[0]]
109
+ definition ? collection_is_array?(definition, definitions) : false
110
+ end
111
+
112
+ def check_send_collection?(node, definitions)
113
+ method_name = node.children[1]
114
+ return true if %i[map select collect flat_map uniq compact].include?(method_name)
115
+ return true if SAFE_TRANSFORM_METHODS.include?(method_name)
116
+
117
+ collection_is_array?(node.children[0], definitions)
110
118
  end
111
119
 
112
- def receiver_ends_with_hash_array_method?(node)
120
+ def receiver_ends_with_safe_transform_method?(node)
113
121
  return false unless node.is_a?(Parser::AST::Node) && node.type == :send
114
122
 
115
- HASH_ARRAY_METHODS.include?(node.children[1]) ||
116
- STRING_ARRAY_METHODS.include?(node.children[1]) ||
117
- BRACKET_ARRAY_METHODS.include?(node.children[1])
123
+ SAFE_TRANSFORM_METHODS.include?(node.children[1])
118
124
  end
119
125
 
120
126
  def add_issue(node)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EagerEye
4
- VERSION = "1.1.9"
4
+ VERSION = "1.1.11"
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.1.9
4
+ version: 1.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - hamzagedikkaya
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-01-11 00:00:00.000000000 Z
11
+ date: 2026-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ast