rubocop-github 0.19.0 → 0.22.0

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.
@@ -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