deprecool 0.1.1 → 0.1.3
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 +9 -1
- data/README.md +2 -1
- data/lib/deprecool/cli.rb +19 -5
- data/lib/deprecool/finder.rb +0 -10
- data/lib/deprecool/finders/rails/v7.1.0/serializer_positional_class_argument.rb +3 -4
- data/lib/deprecool/finders/rails/v8.2.0/no_binds_to_insert_update_delete.rb +54 -0
- data/lib/deprecool/finders/rails/v8.2.0/to_sql_binds.rb +2 -4
- data/lib/deprecool/finders/rails/v8.2.0/write_attribute_id.rb +30 -0
- data/lib/deprecool/finders/ruby/v4.0.0/object_space_id2ref.rb +2 -2
- data/lib/deprecool/finders/ruby/v4.0.0/to_set_arguments.rb +5 -5
- data/lib/deprecool/helpers/prism_helpers.rb +24 -0
- data/lib/deprecool/registry.rb +1 -1
- data/lib/deprecool/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eca3a279e6790babeed0e659c1093f1b1a9086d9695a637460dda7cfa69d7182
|
|
4
|
+
data.tar.gz: a9a735cbd4232f568e002c643370c42491bad699a4ee1cfdd8eaae8e8493c723
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e8ce7b248608aecf4281f836bedc94c5cc6b493a9581145b22d01a9fee87266a304ce389193841dba4c5e1e5e0029af6fb63397b61e7ca877b4bf19e81b974db
|
|
7
|
+
data.tar.gz: 37d39d356843be3105baff39d2f4021b48f9edbf31816b241e715a43f19d489d0b72f3f5abe04de8e4c23749409158c5b5d05470608f3788b618c907faf6c572
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Deprecool
|
|
2
2
|
|
|
3
|
-
## [0.1.
|
|
3
|
+
## [0.1.3] - 2026-08-24
|
|
4
|
+
- Added Finder for: "Passing `binds` as a positional argument to `insert` deprecated", see [original commit](https://github.com/rails/rails/commit/2dca5457ab2097626481fdbec233ea56d3fb9ee3)
|
|
5
|
+
- Added `effort` to the CLI output
|
|
6
|
+
|
|
7
|
+
## [0.1.2] - 2026-08-14
|
|
8
|
+
|
|
9
|
+
- Add Finder for Rails's deprecation of `write_attribute(:id, value)`
|
|
10
|
+
|
|
11
|
+
## [0.1.0], [0.1.1] - 2026-08-13
|
|
4
12
|
|
|
5
13
|
- Initial Release
|
data/README.md
CHANGED
|
@@ -6,7 +6,8 @@ A helpful tool for any developer who has ever ignored a gem's warning and then r
|
|
|
6
6
|
|
|
7
7
|
## Usage
|
|
8
8
|
|
|
9
|
-
Add to your Gemfile: `gem 'deprecool'`
|
|
9
|
+
Add to your Gemfile: `gem 'deprecool'`, and `bundle install`
|
|
10
|
+
|
|
10
11
|
Or directly `gem install deprecool`
|
|
11
12
|
|
|
12
13
|
Then you can run `deprecool` in the command line to get:
|
data/lib/deprecool/cli.rb
CHANGED
|
@@ -24,7 +24,7 @@ module Deprecool
|
|
|
24
24
|
option :gems, type: :array, desc: 'Specify gem name(s) to list which versions have deprecation tracking available'
|
|
25
25
|
|
|
26
26
|
def call(gems:)
|
|
27
|
-
CLI.list_finders(Finder.
|
|
27
|
+
CLI.list_finders(Finder.subclasses)
|
|
28
28
|
|
|
29
29
|
# TODO: REPL to filter through the available finders?
|
|
30
30
|
end
|
|
@@ -116,7 +116,7 @@ module Deprecool
|
|
|
116
116
|
def text_report(offenses, finders)
|
|
117
117
|
if offenses.empty?
|
|
118
118
|
puts colorize('No deprecations found.', :green)
|
|
119
|
-
puts "(#{finders.size} finder
|
|
119
|
+
puts "(#{finders.size} finder(s) active)"
|
|
120
120
|
return
|
|
121
121
|
end
|
|
122
122
|
|
|
@@ -125,10 +125,13 @@ module Deprecool
|
|
|
125
125
|
offenses.each_value do |offense_array|
|
|
126
126
|
offense = offense_array.first
|
|
127
127
|
|
|
128
|
-
puts "\n#{colorize(offense.title, :bold)}
|
|
128
|
+
puts "\n#{colorize(offense.title, :bold)}"
|
|
129
|
+
puts
|
|
129
130
|
puts " * #{offense.summary}"
|
|
130
|
-
puts
|
|
131
|
-
puts " #{colorize('
|
|
131
|
+
puts
|
|
132
|
+
puts " #{colorize('effort:', :green).ljust(16)} #{colorize_effort(offense.effort)}"
|
|
133
|
+
puts " #{colorize('fix:', :green).ljust(16)} #{offense.suggestion}" if offense.suggestion
|
|
134
|
+
puts " #{colorize('source(s):', :green).ljust(16)} #{offense.reference}" if offense.reference
|
|
132
135
|
puts ' Found At:'
|
|
133
136
|
offense_array.each do |o|
|
|
134
137
|
offense_count += 1
|
|
@@ -158,6 +161,17 @@ module Deprecool
|
|
|
158
161
|
|
|
159
162
|
"\e[#{colors.fetch(color, nil)}m#{text}\e[0m"
|
|
160
163
|
end
|
|
164
|
+
|
|
165
|
+
def colorize_effort(effort)
|
|
166
|
+
# the effort method raises if you set anything but these
|
|
167
|
+
# values so it's safe to assume, it would also be a hassle
|
|
168
|
+
# to remove duplication here so oh well
|
|
169
|
+
effort_colors = { low: :green,
|
|
170
|
+
medium: :yellow,
|
|
171
|
+
high: :red }
|
|
172
|
+
|
|
173
|
+
colorize(effort, effort_colors[effort])
|
|
174
|
+
end
|
|
161
175
|
end
|
|
162
176
|
end
|
|
163
177
|
end
|
data/lib/deprecool/finder.rb
CHANGED
|
@@ -31,17 +31,7 @@ module Deprecool
|
|
|
31
31
|
class Finder
|
|
32
32
|
include PrismHelpers
|
|
33
33
|
|
|
34
|
-
@registry = []
|
|
35
|
-
|
|
36
34
|
class << self
|
|
37
|
-
# All finder subclasses, in definition order.
|
|
38
|
-
attr_reader :registry
|
|
39
|
-
|
|
40
|
-
def inherited(subclass)
|
|
41
|
-
Finder.registry << subclass
|
|
42
|
-
super
|
|
43
|
-
end
|
|
44
|
-
|
|
45
35
|
# defines class methods that set instance variables
|
|
46
36
|
%i[gem title summary suggestion reference].each do |attribute|
|
|
47
37
|
define_method(attribute) do |value = (getter = true)|
|
|
@@ -25,11 +25,10 @@ module Deprecool
|
|
|
25
25
|
|
|
26
26
|
def on_call_node(node)
|
|
27
27
|
return unless node.name == :serialize
|
|
28
|
+
return unless arguments_are_length(node.arguments, 2)
|
|
29
|
+
return unless unwrap_arguments(node.arguments)[1].is_a?(Prism::ConstantReadNode)
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
return unless arguments_array && arguments_array[1]
|
|
31
|
-
|
|
32
|
-
add_offense(node, confidence: :high) if arguments_array[1].is_a?(Prism::ConstantReadNode)
|
|
31
|
+
add_offense(node, confidence: :high)
|
|
33
32
|
end
|
|
34
33
|
end
|
|
35
34
|
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Deprecool
|
|
4
|
+
module Finders
|
|
5
|
+
module Rails
|
|
6
|
+
module V8_2_0
|
|
7
|
+
class InsertUpdateDeleteBinds < Deprecool::Finder
|
|
8
|
+
gem :rails
|
|
9
|
+
deprecated_in '8.2.0'
|
|
10
|
+
removed_in '9.0.0'
|
|
11
|
+
title 'Binds being bassed to Insert Update Delete is deprecated'
|
|
12
|
+
summary ' Now that `Arel.sql(sql_with_placeholders, *binds)` wraps SQL and its binds' \
|
|
13
|
+
'together as an `Arel::Nodes::BoundSqlLiteral`, just like ' \
|
|
14
|
+
'`Model.where("... = ?", value)`, the separate positional is no longer needed'
|
|
15
|
+
suggestion 'Old: `connection.insert("INSERT INTO topics (title) VALUES (?)", nil, nil, ["hello"])` ' \
|
|
16
|
+
'New: `connection.insert(Arel.sql("INSERT INTO topics (title) VALUES (?)", "hello"))`'
|
|
17
|
+
reference 'Original Commit: https://github.com/rails/rails/commit/2dca5457ab2097626481fdbec233ea56d3fb9ee3'
|
|
18
|
+
effort :low
|
|
19
|
+
|
|
20
|
+
def on_call_node(node)
|
|
21
|
+
return unless %i[insert update delete].include?(node.name)
|
|
22
|
+
return unless arguments = unwrap_arguments(node.arguments)
|
|
23
|
+
return unless arguments.length > 1
|
|
24
|
+
|
|
25
|
+
confidence = confidence_from_arguments(arguments)
|
|
26
|
+
return if confidence == :none
|
|
27
|
+
|
|
28
|
+
add_offense(node, confidence: confidence)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def confidence_from_arguments(arguments)
|
|
34
|
+
first = arguments[0]
|
|
35
|
+
|
|
36
|
+
# if first argument is string node that starts with "INSERT" "UPDATE" "DELETE" then :high
|
|
37
|
+
# if first argument is a variable then :low confidence
|
|
38
|
+
# it it's a Prism::CallNode, and not a variable call, then I don't know what it is here,
|
|
39
|
+
# maybe it's like 'connection.update(generate_sql(some_arg), ["name"])' and if you are doing that
|
|
40
|
+
# then good luck?
|
|
41
|
+
if first.is_a?(Prism::CallNode)
|
|
42
|
+
return :low if first.variable_call? # can't tell what's stored in the variable, https://docs.ruby-lang.org/en/master/Prism/CallNode.html#method-i-variable_call-3F
|
|
43
|
+
:none
|
|
44
|
+
elsif %w[INSERT UPDATE DELETE].include?(first.unescaped[..5].upcase)
|
|
45
|
+
:high
|
|
46
|
+
else
|
|
47
|
+
:none
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -7,7 +7,7 @@ module Deprecool
|
|
|
7
7
|
class ToSqlBinds < Deprecool::Finder
|
|
8
8
|
gem :rails
|
|
9
9
|
deprecated_in '8.2.0'
|
|
10
|
-
removed_in '
|
|
10
|
+
removed_in '9.0.0'
|
|
11
11
|
title 'Passing "binds" into "to_sql" is deprecated'
|
|
12
12
|
summary 'Since Rails 5.2, bind parameters live on the Arel AST ' \
|
|
13
13
|
'to_sql_and_binds no longer uses binds for SQL construction, ' \
|
|
@@ -26,9 +26,7 @@ module Deprecool
|
|
|
26
26
|
# if a method called 'to_sql' is passed two arguments and the second is an
|
|
27
27
|
# array that's probably good enough
|
|
28
28
|
return unless node.name == :to_sql
|
|
29
|
-
|
|
30
|
-
arguments_array = unwrap_arguments(node.arguments)
|
|
31
|
-
return unless arguments_array && arguments_array[1]
|
|
29
|
+
return unless arguments_are_length(node.arguments, 2)
|
|
32
30
|
|
|
33
31
|
add_offense(node, confidence: :high)
|
|
34
32
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Deprecool
|
|
4
|
+
module Finders
|
|
5
|
+
module Rails
|
|
6
|
+
module V8_2_0
|
|
7
|
+
class WriteAttributeId < Deprecool::Finder
|
|
8
|
+
gem :rails
|
|
9
|
+
deprecated_in '8.2.0'
|
|
10
|
+
removed_in '9.0.0'
|
|
11
|
+
title 'Using "write_attribute" for the primary key is deprecated'
|
|
12
|
+
summary 'Just like Rails 7.1\'s deprecation of calling "read_attribute(:id)", '\
|
|
13
|
+
'"write_attribute(:id)" is now deprecated and will be removed in the next version of Rails. ' \
|
|
14
|
+
'making :id refer only to the id column, not the primary key.'
|
|
15
|
+
suggestion 'Use "#id=" on a model whose primary key is not named "id"'
|
|
16
|
+
reference 'Original Rails Commit: https://github.com/rails/rails/commit/1a90632bbe62dae2626de7a058bc18c29f77aea6'
|
|
17
|
+
effort :low
|
|
18
|
+
|
|
19
|
+
def on_call_node(node)
|
|
20
|
+
return unless node.name == :write_attribute
|
|
21
|
+
return unless arguments_are_length(node.arguments, 2)
|
|
22
|
+
return unless arguments_contain(node.arguments, "id", position: 0)
|
|
23
|
+
|
|
24
|
+
add_offense(node, confidence: :high)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -27,9 +27,9 @@ module Deprecool
|
|
|
27
27
|
# I don't think we need much more than this
|
|
28
28
|
# I'm open to be wrong though, maybe lots of people are subclassing
|
|
29
29
|
# ObjectSpace or defining '_id2ref' on custom classes
|
|
30
|
-
confidence = node.receiver.name == :ObjectSpace ? :high :
|
|
30
|
+
confidence = node.receiver.name == :ObjectSpace ? :high : :none
|
|
31
31
|
|
|
32
|
-
return
|
|
32
|
+
return if confidence == :none
|
|
33
33
|
|
|
34
34
|
add_offense node, confidence: confidence
|
|
35
35
|
end
|
|
@@ -11,8 +11,8 @@ module Deprecool
|
|
|
11
11
|
title 'Passing arguments to #to_set is deprecated'
|
|
12
12
|
summary 'Since Ruby 4.0, passing arguments to Set#to_set / Enumerable#to_set ' \
|
|
13
13
|
'is deprecated and will be removed.'
|
|
14
|
-
suggestion 'Call #to_set with no arguments. If you
|
|
15
|
-
'
|
|
14
|
+
suggestion 'Call #to_set with no arguments. If you want an instance of a subclass of Set' \
|
|
15
|
+
'from an enumerable construct it explicitly instead: MySetSubclass.new(enumerable)'
|
|
16
16
|
reference 'https://bugs.ruby-lang.org/issues/21390 https://github.com/ruby/ruby/pull/13489'
|
|
17
17
|
effort :low
|
|
18
18
|
|
|
@@ -21,7 +21,7 @@ module Deprecool
|
|
|
21
21
|
return unless node.arguments
|
|
22
22
|
|
|
23
23
|
confidence = confidence_from_receiver_node(node.receiver)
|
|
24
|
-
return
|
|
24
|
+
return if confidence == :none
|
|
25
25
|
|
|
26
26
|
add_offense(node, confidence:)
|
|
27
27
|
end
|
|
@@ -35,12 +35,12 @@ module Deprecool
|
|
|
35
35
|
# a plain `to_set(x)` call to the current scope's own
|
|
36
36
|
# method. This is probably not Enumerable#to_set unless someone has
|
|
37
37
|
# monkeypatched Enumerable and is using to_set with an argument, I guess
|
|
38
|
-
when nil then
|
|
38
|
+
when nil then :none
|
|
39
39
|
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
|
40
40
|
# These nodes can constants like:
|
|
41
41
|
# MY_DATA.to_set(arg) => likely an array, but can't be sure so :low
|
|
42
42
|
# MyClass.to_set(arg) => has lowercase letters so it's a class method
|
|
43
|
-
receiver&.name&.match?(/[a-z]/) ?
|
|
43
|
+
receiver&.name&.match?(/[a-z]/) ? :none : :low
|
|
44
44
|
else
|
|
45
45
|
# this branch is when the receiver is some
|
|
46
46
|
# local var, instance variable, method chain, safe navigation, etc.
|
|
@@ -36,4 +36,28 @@ module PrismHelpers
|
|
|
36
36
|
|
|
37
37
|
node.child_nodes
|
|
38
38
|
end
|
|
39
|
+
|
|
40
|
+
def arguments_are_length(node, length)
|
|
41
|
+
return false unless node.is_a?(Prism::ArgumentsNode)
|
|
42
|
+
|
|
43
|
+
unwrap_arguments(node.arguments).length == length
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def arguments_contain(node, value, position: -1, kwarg: nil)
|
|
47
|
+
return false unless node.is_a?(Prism::ArgumentsNode)
|
|
48
|
+
|
|
49
|
+
arguments = unwrap_arguments(node)
|
|
50
|
+
|
|
51
|
+
return (value_from_argument(arguments[position]) == value) if position >= 0
|
|
52
|
+
|
|
53
|
+
arguments.any? do |arg|
|
|
54
|
+
value_from_argument(arg) == value
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def value_from_argument(node)
|
|
59
|
+
case node
|
|
60
|
+
when Prism::SymbolNode, Prism::StringNode then node.unescaped
|
|
61
|
+
end
|
|
62
|
+
end
|
|
39
63
|
end
|
data/lib/deprecool/registry.rb
CHANGED
data/lib/deprecool/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: deprecool
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Zac Radford
|
|
@@ -56,8 +56,10 @@ files:
|
|
|
56
56
|
- lib/deprecool/cli.rb
|
|
57
57
|
- lib/deprecool/finder.rb
|
|
58
58
|
- lib/deprecool/finders/rails/v7.1.0/serializer_positional_class_argument.rb
|
|
59
|
+
- lib/deprecool/finders/rails/v8.2.0/no_binds_to_insert_update_delete.rb
|
|
59
60
|
- lib/deprecool/finders/rails/v8.2.0/redis_cache_store_default_redis_options.rb
|
|
60
61
|
- lib/deprecool/finders/rails/v8.2.0/to_sql_binds.rb
|
|
62
|
+
- lib/deprecool/finders/rails/v8.2.0/write_attribute_id.rb
|
|
61
63
|
- lib/deprecool/finders/ruby/v4.0.0/object_space_id2ref.rb
|
|
62
64
|
- lib/deprecool/finders/ruby/v4.0.0/to_set_arguments.rb
|
|
63
65
|
- lib/deprecool/helpers/prism_helpers.rb
|