bulletmark_repairer 0.1.2 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codespellignore +0 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +15 -1
- data/README.md +6 -8
- data/lib/bulletmark_repairer/configuration.rb +2 -2
- data/lib/bulletmark_repairer/controller_corrector.rb +5 -4
- data/lib/bulletmark_repairer/corrector_builder.rb +24 -11
- data/lib/bulletmark_repairer/markers.rb +17 -3
- data/lib/bulletmark_repairer/retry_corrector.rb +39 -0
- data/lib/bulletmark_repairer/version.rb +1 -1
- metadata +4 -3
- data/lib/bulletmark_repairer/corrector.rb +0 -56
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b793a019d2937170c113a1b95eeea035a23e0f85a36f5c86382628467d3b006
|
4
|
+
data.tar.gz: 0e513ae03aab2b2f21785d31be5141abe0a34759a16a97e41b32871caf01d531
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb0869546bfe5bd2c29586cffc2261f58680bb114a7f5dd01c0d4325df6736d49e24e743200285eb5cf199b87123e22bfe85cb8dce0eb2546d469e71fd98afd9
|
7
|
+
data.tar.gz: 2ef8b880ef7e027b3a49a08638235a342ad8e8f1c7a35485f01f3c3cbbbb09b8cd4b75ec21b7522a2439e685833b05ed9488d3a75c916df8391453ea618f7aa8
|
data/.codespellignore
ADDED
File without changes
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,17 @@
|
|
1
|
+
## [0.1.4] - 2023-10-22
|
2
|
+
|
3
|
+
- Patch files other than controllers [218566d](https://github.com/makicamel/bulletmark_repairer/commit/218566d1531751f204941c3dcff7f095a056d39f)
|
4
|
+
- Patch unassigned queries [159573a](https://github.com/makicamel/bulletmark_repairer/commit/159573ada036ee3ee39428b1e59066934b676c02)
|
5
|
+
- Apply patches starting from the top of the method [f8d0058](https://github.com/makicamel/bulletmark_repairer/commit/f8d00582a5b3b084c0a35a54726396a2a063f8dd)
|
6
|
+
- Log also when the target file is in the skip list [a23a3bc](https://github.com/makicamel/bulletmark_repairer/commit/a23a3bc0edf1e94d3aa6ea95449c9570b9322d65)
|
7
|
+
|
8
|
+
## [0.1.3] - 2023-10-18
|
9
|
+
|
10
|
+
- Fix a redundant auto-correct for multiple tests with n+1 queries when running RSpec [#6](https://github.com/makicamel/bulletmark_repairer/pull/6) ([@ydah])
|
11
|
+
|
1
12
|
## [0.1.2] - 2023-10-16
|
2
13
|
|
3
|
-
- Reduce dependencies [#1](https://github.com/makicamel/bulletmark_repairer/pull/1) [@tricknotes]
|
14
|
+
- Reduce dependencies [#1](https://github.com/makicamel/bulletmark_repairer/pull/1) ([@tricknotes])
|
4
15
|
- Stop using class instance variables for thread safe [024f6c5](https://github.com/makicamel/bulletmark_repairer/commit/024f6c53f82b182a998c1e43de48d8c6c9ce5bf3)
|
5
16
|
|
6
17
|
## [0.1.1] - 2023-10-11
|
@@ -10,3 +21,6 @@
|
|
10
21
|
## [0.1.0] - 2023-10-10
|
11
22
|
|
12
23
|
- Initial release
|
24
|
+
|
25
|
+
[@tricknotes]: https://github.com/tricknotes
|
26
|
+
[@ydah]: https://github.com/ydah
|
data/README.md
CHANGED
@@ -47,14 +47,12 @@ For example, the following cases are not supported as known cases currently:
|
|
47
47
|
|
48
48
|
```ruby
|
49
49
|
def index
|
50
|
-
#
|
51
|
-
Play.
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
plays = Play.all.as_json
|
57
|
-
@play = plays.last
|
50
|
+
# Nested associations require `includes` though child associations are already included
|
51
|
+
@plays = Play.includes(:actors)
|
52
|
+
# expected correct
|
53
|
+
@plays = Play.includes(actors: [:company])
|
54
|
+
# actual correct
|
55
|
+
@plays = Play.includes(:actors).includes([:company])
|
58
56
|
end
|
59
57
|
```
|
60
58
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module BulletmarkRepairer
|
4
|
-
class
|
4
|
+
class Configuration
|
5
5
|
attr_accessor :skip_file_list, :logger
|
6
6
|
attr_writer :debug
|
7
7
|
|
@@ -22,7 +22,7 @@ module BulletmarkRepairer
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def config
|
25
|
-
@config ||=
|
25
|
+
@config ||= Configuration.new
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -46,14 +46,15 @@ class ControllerCorrector < Parser::TreeRewriter
|
|
46
46
|
return unless node.respond_to?(:to_sexp_array)
|
47
47
|
|
48
48
|
type, identifier = node.to_sexp_array.take(2)
|
49
|
-
|
50
49
|
if type == :ivasgn && identifier == instance_variable_name
|
51
|
-
|
52
|
-
|
50
|
+
inserted = ".includes(#{associations})"
|
51
|
+
unless node.location.expression.source.include?(inserted)
|
52
|
+
insert_after node.children.last.location.expression, inserted
|
53
|
+
@patched = true
|
54
|
+
end
|
53
55
|
else
|
54
56
|
node
|
55
57
|
.children
|
56
|
-
.reverse
|
57
58
|
.each do |child_node|
|
58
59
|
child_type, _, child_identifier = child_node.try(:to_sexp_array)
|
59
60
|
if child_type == :send && target_nodes.key?(child_identifier)
|
@@ -16,17 +16,30 @@ module BulletmarkRepairer
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def execute
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
19
|
+
if @marker.retry
|
20
|
+
corrector_name = '/retry_corrector.rb'
|
21
|
+
File.open("#{@dir}#{corrector_name}", 'w') do |f|
|
22
|
+
corrector = Pathname.new(__FILE__).sub('/corrector_builder.rb', corrector_name)
|
23
|
+
src = File.read(corrector)
|
24
|
+
src
|
25
|
+
.sub!(ASSOCIATIONS, @associations[:base].to_s)
|
26
|
+
.sub!(LINE_NO, @marker.line_no)
|
27
|
+
f.puts src
|
28
|
+
f
|
29
|
+
end.path
|
30
|
+
else
|
31
|
+
corrector_name = '/controller_corrector.rb'
|
32
|
+
File.open("#{@dir}#{corrector_name}", 'w') do |f|
|
33
|
+
corrector = Pathname.new(__FILE__).sub('/corrector_builder.rb', corrector_name)
|
34
|
+
src = File.read(corrector)
|
35
|
+
src
|
36
|
+
.sub!(ASSOCIATIONS, @associations[:base].to_s)
|
37
|
+
.sub!(ACTION, @action)
|
38
|
+
.sub!(INSTANCE_VARIABLE_NAME, @instance_variable_name)
|
39
|
+
f.puts src
|
40
|
+
f
|
41
|
+
end.path
|
42
|
+
end
|
30
43
|
end
|
31
44
|
end
|
32
45
|
end
|
@@ -28,7 +28,7 @@ module BulletmarkRepairer
|
|
28
28
|
end
|
29
29
|
|
30
30
|
class Marker
|
31
|
-
attr_reader :base_class, :associations, :action, :file_name, :instance_variable_name, :index
|
31
|
+
attr_reader :base_class, :associations, :action, :file_name, :instance_variable_name, :index, :retry, :line_no
|
32
32
|
|
33
33
|
def initialize(notification, controller:, action:)
|
34
34
|
@base_class = notification.instance_variable_get(:@base_class)
|
@@ -36,6 +36,8 @@ module BulletmarkRepairer
|
|
36
36
|
@associations = notification.instance_variable_get(:@associations)
|
37
37
|
@controller = controller
|
38
38
|
@action = action
|
39
|
+
@retry = false
|
40
|
+
@line_no = nil
|
39
41
|
set_up
|
40
42
|
end
|
41
43
|
|
@@ -56,6 +58,7 @@ module BulletmarkRepairer
|
|
56
58
|
|
57
59
|
def log_patchable_files_not_be_found
|
58
60
|
return if index
|
61
|
+
return if BulletmarkRepairer.config.skip_file_list.exclude?(file_name.remove("#{Rails.root}/"))
|
59
62
|
|
60
63
|
BulletmarkRepairer.config.logger.info <<~LOG
|
61
64
|
Repairer couldn't patch
|
@@ -93,7 +96,6 @@ module BulletmarkRepairer
|
|
93
96
|
@index = @instance_variable_name ? "#{view_file}:#{view_yield_index}" : nil
|
94
97
|
else
|
95
98
|
# TODO: Ignore controllers list
|
96
|
-
# TODO: Allow directories list
|
97
99
|
controller_file_index = @stacktraces.index { |stacktrace| stacktrace.match?(%r{\A(#{Rails.root}/app/controllers[./\w]+):(\d+):in `[()\w\s]+'\z}) }
|
98
100
|
@file_name, controller_yield_index = @stacktraces[controller_file_index].scan(%r{\A(#{Rails.root}/app/controllers[./\w]+):(\d+):in `[()\w\s]+'\z}).flatten
|
99
101
|
controller_yield_index = controller_yield_index.to_i
|
@@ -104,13 +106,25 @@ module BulletmarkRepairer
|
|
104
106
|
|
105
107
|
controller_yield_index -= 1
|
106
108
|
line = lines[controller_yield_index]
|
107
|
-
# TODO: patch to local variables
|
108
109
|
@instance_variable_name = line&.scan(/\b?(@[\w]+)\b?/)&.flatten&.last
|
109
110
|
break if line.match?(/^\s+def [()\w\s=]+$/)
|
110
111
|
end
|
111
112
|
end
|
112
113
|
@index = @instance_variable_name ? "#{@file_name}:#{controller_yield_index}" : nil
|
113
114
|
end
|
115
|
+
|
116
|
+
return if @index
|
117
|
+
|
118
|
+
# TODO: Ignore files list
|
119
|
+
# TODO: Allow model files list
|
120
|
+
@retry = @stacktraces.any? do |stacktrace|
|
121
|
+
!stacktrace.match?(%r{\A(#{Rails.root}/app/models[./\w]+):(\d+):in `[()\w\s=!?]+'\z}) &&
|
122
|
+
stacktrace =~ %r{\A(#{Rails.root}/app[./\w]+):(\d+):in `[()\w\s=!?]+'\z}
|
123
|
+
end.tap do
|
124
|
+
@file_name = Regexp.last_match(1)
|
125
|
+
@line_no = Regexp.last_match(2)
|
126
|
+
end
|
127
|
+
@index = @retry ? "#{@file_name}:#{@line_no}" : nil
|
114
128
|
end
|
115
129
|
end
|
116
130
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RetryCorrector < Parser::TreeRewriter
|
4
|
+
def on_def(node)
|
5
|
+
return if patched?
|
6
|
+
|
7
|
+
node.children.each { |child_node| insert_includes(node: child_node) }
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def patched?
|
13
|
+
@patched ||= false
|
14
|
+
end
|
15
|
+
|
16
|
+
def insert_includes(node:)
|
17
|
+
return if patched?
|
18
|
+
return if !node.respond_to?(:children) || node.children.empty?
|
19
|
+
return unless node.location.expression.line <= line_no && line_no <= node.location.expression.last_line
|
20
|
+
|
21
|
+
if node.type == :begin
|
22
|
+
node.children.each { |child_node| insert_includes(node: child_node) }
|
23
|
+
else
|
24
|
+
inserted = ".includes(#{associations})"
|
25
|
+
return if node.location.expression.source.include?(inserted)
|
26
|
+
|
27
|
+
insert_after node.location.expression, ".includes(#{associations})"
|
28
|
+
@patched = true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def line_no
|
33
|
+
__EMBEDDED_LINE_NO__
|
34
|
+
end
|
35
|
+
|
36
|
+
def associations
|
37
|
+
'__EMBEDDED_ASSOCIATIONS__'
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bulletmark_repairer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- makicamel
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -73,6 +73,7 @@ executables: []
|
|
73
73
|
extensions: []
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
|
+
- ".codespellignore"
|
76
77
|
- ".rspec"
|
77
78
|
- ".rubocop.yml"
|
78
79
|
- CHANGELOG.md
|
@@ -86,12 +87,12 @@ files:
|
|
86
87
|
- lib/bulletmark_repairer/associations_builder.rb
|
87
88
|
- lib/bulletmark_repairer/configuration.rb
|
88
89
|
- lib/bulletmark_repairer/controller_corrector.rb
|
89
|
-
- lib/bulletmark_repairer/corrector.rb
|
90
90
|
- lib/bulletmark_repairer/corrector_builder.rb
|
91
91
|
- lib/bulletmark_repairer/markers.rb
|
92
92
|
- lib/bulletmark_repairer/patcher.rb
|
93
93
|
- lib/bulletmark_repairer/rack.rb
|
94
94
|
- lib/bulletmark_repairer/railtie.rb
|
95
|
+
- lib/bulletmark_repairer/retry_corrector.rb
|
95
96
|
- lib/bulletmark_repairer/version.rb
|
96
97
|
- sig/bulletmark_repairer.rbs
|
97
98
|
homepage: https://github.com/makicamel/bulletmark_repairer
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Corrector < Parser::TreeRewriter
|
4
|
-
def on_def(node)
|
5
|
-
return if patched?
|
6
|
-
|
7
|
-
node.children.each { |child_node| insert_includes(node: child_node) }
|
8
|
-
return if patched?
|
9
|
-
|
10
|
-
node.children.each { |child_node| insert_includes_for_vasgn(node: child_node, type: :ivasgn) }
|
11
|
-
return if patched?
|
12
|
-
|
13
|
-
node.children.each { |child_node| insert_includes_for_vasgn(node: child_node, type: :lvasgn) }
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def patched?
|
19
|
-
@patched ||= false
|
20
|
-
end
|
21
|
-
|
22
|
-
def insert_includes(node:)
|
23
|
-
return if patched?
|
24
|
-
return if !node.respond_to?(:children) || node.children.empty?
|
25
|
-
return unless node.location.expression.line <= line_no && line_no <= node.location.expression.last_line
|
26
|
-
|
27
|
-
# TODO: Patch Enumerable methods other than each and map
|
28
|
-
if node.children.last.in?(%i[each map])
|
29
|
-
insert_after node.children[0].location.expression, ".includes(#{associations})"
|
30
|
-
@patched = true
|
31
|
-
else
|
32
|
-
node.children.each { |child_node| insert_includes(node: child_node) }
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def insert_includes_for_vasgn(node:, type:)
|
37
|
-
return if patched?
|
38
|
-
return if !node.respond_to?(:children) || node.children.empty?
|
39
|
-
return unless node.location.expression.line <= line_no && line_no <= node.location.expression.last_line
|
40
|
-
|
41
|
-
if node.type == type
|
42
|
-
insert_after node.children.last.location.expression, ".includes(#{associations})"
|
43
|
-
@patched = true
|
44
|
-
else
|
45
|
-
node.children.each { |child_node| insert_includes_for_vasgn(node: child_node, type: type) }
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def line_no
|
50
|
-
__EMBEDDED_LINE_NO__
|
51
|
-
end
|
52
|
-
|
53
|
-
def associations
|
54
|
-
'__EMBEDDED_ASSOCIATIONS__'
|
55
|
-
end
|
56
|
-
end
|