rubocop-github 0.19.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module GitHub
8
+ # Public: A Rubocop to discourage using methods like Object#send that allow you to dynamically call other
9
+ # methods on a Ruby object, when the method being called is itself completely dynamic. Instead, explicitly call
10
+ # methods by name.
11
+ #
12
+ # Examples:
13
+ #
14
+ # # bad
15
+ # foo.send(some_variable)
16
+ #
17
+ # # good
18
+ # case some_variable
19
+ # when "bar"
20
+ # foo.bar
21
+ # else
22
+ # foo.baz
23
+ # end
24
+ #
25
+ # # fine
26
+ # foo.send(:bar)
27
+ # foo.public_send("some_method")
28
+ # foo.__send__("some_#{variable}_method")
29
+ class AvoidObjectSendWithDynamicMethod < Base
30
+ MESSAGE_TEMPLATE = "Avoid using Object#%s with a dynamic method name."
31
+ SEND_METHODS = %i(send public_send __send__).freeze
32
+ CONSTANT_TYPES = %i(sym str const).freeze
33
+
34
+ def on_send(node)
35
+ return unless send_method?(node)
36
+ return if method_being_sent_is_constrained?(node)
37
+ add_offense(source_range_for_method_call(node), message: MESSAGE_TEMPLATE % node.method_name)
38
+ end
39
+
40
+ private
41
+
42
+ def send_method?(node)
43
+ SEND_METHODS.include?(node.method_name)
44
+ end
45
+
46
+ def method_being_sent_is_constrained?(node)
47
+ method_name_being_sent_is_constant?(node) || method_name_being_sent_is_dynamic_string_with_constants?(node)
48
+ end
49
+
50
+ def method_name_being_sent_is_constant?(node)
51
+ method_being_sent = node.arguments.first
52
+ # e.g., `worker.send(:perform)` or `base.send("extend", Foo)`
53
+ CONSTANT_TYPES.include?(method_being_sent.type)
54
+ end
55
+
56
+ def method_name_being_sent_is_dynamic_string_with_constants?(node)
57
+ method_being_sent = node.arguments.first
58
+ return false unless method_being_sent.type == :dstr
59
+
60
+ # e.g., `foo.send("can_#{action}?")`
61
+ method_being_sent.child_nodes.any? { |child_node| CONSTANT_TYPES.include?(child_node.type) }
62
+ end
63
+
64
+ def source_range_for_method_call(node)
65
+ begin_pos =
66
+ if node.receiver # e.g., for `foo.send(:bar)`, `foo` is the receiver
67
+ node.receiver.source_range.end_pos
68
+ else # e.g., `send(:bar)`
69
+ node.source_range.begin_pos
70
+ end
71
+ end_pos = node.loc.selector.end_pos
72
+ Parser::Source::Range.new(processed_source.buffer, begin_pos, end_pos)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -9,7 +9,7 @@ module RuboCop
9
9
  class RailsControllerRenderLiteral < Base
10
10
  include RenderLiteralHelpers
11
11
 
12
- MSG = "render must be used with a string literal or an instance of a Class"
12
+ MSG = "render must be used with a string literal or an instance of a Class, and use literals for locals keys"
13
13
 
14
14
  def_node_matcher :ignore_key?, <<-PATTERN
15
15
  (pair (sym {
@@ -6,6 +6,8 @@ module RuboCop
6
6
  module Cop
7
7
  module GitHub
8
8
  class RailsViewRenderShorthand < Base
9
+ extend AutoCorrector
10
+
9
11
  MSG = "Prefer `render` partial shorthand"
10
12
 
11
13
  def_node_matcher :render_with_options?, <<-PATTERN
@@ -26,9 +28,13 @@ module RuboCop
26
28
  locals_key = option_pairs.map { |pair| locals_key?(pair) }.compact.first
27
29
 
28
30
  if option_pairs.length == 1 && partial_key
29
- add_offense(node, message: "Use `render #{partial_key.source}` instead")
31
+ add_offense(node, message: "Use `render #{partial_key.source}` instead") do |corrector|
32
+ corrector.replace(node.source_range, "render #{partial_key.source}")
33
+ end
30
34
  elsif option_pairs.length == 2 && partial_key && locals_key
31
- add_offense(node, message: "Use `render #{partial_key.source}, #{locals_key.source}` instead")
35
+ add_offense(node, message: "Use `render #{partial_key.source}, #{locals_key.source}` instead") do |corrector|
36
+ corrector.replace(node.source_range, "render #{partial_key.source}, #{locals_key.source}")
37
+ end
32
38
  end
33
39
  end
34
40
  end
@@ -41,7 +41,8 @@ module RuboCop
41
41
  PATTERN
42
42
 
43
43
  def hash_with_literal_keys?(hash)
44
- hash.pairs.all? { |pair| literal?(pair.key) }
44
+ hash.children.all? { |child| child.pair_type? } &&
45
+ hash.pairs.all? { |pair| literal?(pair.key) }
45
46
  end
46
47
 
47
48
  def render_view_component?(node)
@@ -6,12 +6,10 @@ require "rubocop/github/inject"
6
6
 
7
7
  RuboCop::GitHub::Inject.rails_defaults!
8
8
 
9
- require "rubocop/cop/github/rails_application_record"
10
9
  require "rubocop/cop/github/rails_controller_render_action_symbol"
11
10
  require "rubocop/cop/github/rails_controller_render_literal"
12
11
  require "rubocop/cop/github/rails_controller_render_paths_exist"
13
12
  require "rubocop/cop/github/rails_controller_render_shorthand"
14
- require "rubocop/cop/github/rails_render_inline"
15
13
  require "rubocop/cop/github/rails_render_object_collection"
16
14
  require "rubocop/cop/github/rails_view_render_literal"
17
15
  require "rubocop/cop/github/rails_view_render_paths_exist"
@@ -6,4 +6,5 @@ require "rubocop/github/inject"
6
6
 
7
7
  RuboCop::GitHub::Inject.default_defaults!
8
8
 
9
+ require "rubocop/cop/github/avoid_object_send_with_dynamic_method"
9
10
  require "rubocop/cop/github/insecure_hash_algorithm"
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ VERSION = "0.22.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-github
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.0
4
+ version: 0.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-13 00:00:00.000000000 Z
11
+ date: 2025-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -16,42 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.0.0
19
+ version: '1.37'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 1.0.0
26
+ version: '1.37'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rubocop-performance
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1.15'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '1.15'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rubocop-rails
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '2.17'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '2.17'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: actionview
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -94,7 +94,7 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- description: 'Code style checking for GitHub Ruby repositories '
97
+ description: Code style checking for GitHub Ruby repositories
98
98
  email: engineering@github.com
99
99
  executables: []
100
100
  extensions: []
@@ -105,21 +105,21 @@ files:
105
105
  - STYLEGUIDE.md
106
106
  - config/default.yml
107
107
  - config/default_cops.yml
108
+ - config/default_pending.yml
108
109
  - config/rails.yml
109
110
  - config/rails_cops.yml
111
+ - config/rails_pending.yml
110
112
  - guides/rails-controller-render-shorthand.md
111
- - guides/rails-render-inline.md
112
113
  - guides/rails-render-literal.md
113
114
  - lib/rubocop-github-rails.rb
114
115
  - lib/rubocop-github.rb
115
116
  - lib/rubocop/cop/github.rb
117
+ - lib/rubocop/cop/github/avoid_object_send_with_dynamic_method.rb
116
118
  - lib/rubocop/cop/github/insecure_hash_algorithm.rb
117
- - lib/rubocop/cop/github/rails_application_record.rb
118
119
  - lib/rubocop/cop/github/rails_controller_render_action_symbol.rb
119
120
  - lib/rubocop/cop/github/rails_controller_render_literal.rb
120
121
  - lib/rubocop/cop/github/rails_controller_render_paths_exist.rb
121
122
  - lib/rubocop/cop/github/rails_controller_render_shorthand.rb
122
- - lib/rubocop/cop/github/rails_render_inline.rb
123
123
  - lib/rubocop/cop/github/rails_render_object_collection.rb
124
124
  - lib/rubocop/cop/github/rails_view_render_literal.rb
125
125
  - lib/rubocop/cop/github/rails_view_render_paths_exist.rb
@@ -127,10 +127,14 @@ files:
127
127
  - lib/rubocop/cop/github/render_literal_helpers.rb
128
128
  - lib/rubocop/github.rb
129
129
  - lib/rubocop/github/inject.rb
130
+ - lib/version.rb
130
131
  homepage: https://github.com/github/rubocop-github
131
132
  licenses:
132
133
  - MIT
133
- metadata: {}
134
+ metadata:
135
+ source_code_uri: https://github.com/github/rubocop-github
136
+ documentation_uri: https://github.com/github/rubocop-github
137
+ bug_tracker_uri: https://github.com/github/rubocop-github/issues
134
138
  post_install_message:
135
139
  rdoc_options: []
136
140
  require_paths:
@@ -139,14 +143,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
139
143
  requirements:
140
144
  - - ">="
141
145
  - !ruby/object:Gem::Version
142
- version: 2.5.0
146
+ version: 3.0.0
143
147
  required_rubygems_version: !ruby/object:Gem::Requirement
144
148
  requirements:
145
149
  - - ">="
146
150
  - !ruby/object:Gem::Version
147
151
  version: '0'
148
152
  requirements: []
149
- rubygems_version: 3.3.7
153
+ rubygems_version: 3.4.6
150
154
  signing_key:
151
155
  specification_version: 4
152
156
  summary: RuboCop GitHub
@@ -1,27 +0,0 @@
1
- # GitHub/RailsRenderInline
2
-
3
- tldr; Do not use `render inline:`.
4
-
5
- ## Rendering plain text
6
-
7
- ``` ruby
8
- render inline: "Just plain text" # bad
9
- ```
10
-
11
- The `inline:` option is often misused when plain text is being returned. Instead use `render plain: "Just plain text"`.
12
-
13
- ## Rendering a dynamic ERB string
14
-
15
- String `#{}` interpolation is often misused with `render inline:` instead of using `<%= %>` interpolation. This will lead to a memory leak where an ERB method will be compiled and cached for each invocation of `render inline:`.
16
-
17
- ``` ruby
18
- render inline: "Hello #{@name}" # bad
19
- ```
20
-
21
- ## Rendering static ERB strings
22
-
23
- ``` ruby
24
- render inline: "Hello <%= @name %>" # bad
25
- ```
26
-
27
- If you are passing a static ERB string to `render inline:`, this string is best moved to a `.erb` template under `app/views`. Template files are able to be precompiled at boot time.
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rubocop"
4
-
5
- module RuboCop
6
- module Cop
7
- module GitHub
8
- class RailsApplicationRecord < Base
9
- MSG = "Models should subclass from ApplicationRecord"
10
-
11
- def_node_matcher :active_record_base_const?, <<-PATTERN
12
- (const (const nil? :ActiveRecord) :Base)
13
- PATTERN
14
-
15
- def_node_matcher :application_record_const?, <<-PATTERN
16
- (const nil? :ApplicationRecord)
17
- PATTERN
18
-
19
- def on_class(node)
20
- klass, superclass, _ = *node
21
-
22
- if active_record_base_const?(superclass) && !(application_record_const?(klass))
23
- add_offense(superclass)
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rubocop"
4
-
5
- module RuboCop
6
- module Cop
7
- module GitHub
8
- class RailsRenderInline < Base
9
- MSG = "Avoid `render inline:`"
10
-
11
- def_node_matcher :render_with_options?, <<-PATTERN
12
- (send nil? {:render :render_to_string} (hash $...))
13
- PATTERN
14
-
15
- def_node_matcher :inline_key?, <<-PATTERN
16
- (pair (sym :inline) $_)
17
- PATTERN
18
-
19
- def on_send(node)
20
- if option_pairs = render_with_options?(node)
21
- if option_pairs.detect { |pair| inline_key?(pair) }
22
- add_offense(node)
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end