rubocop-platanus 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +3 -2
- data/README.md +1 -1
- data/config/default.yml +32 -0
- data/lib/rubocop/cop/platanus/no_enumerize.rb +85 -0
- data/lib/rubocop/cop/platanus/no_flash_in_api.rb +48 -0
- data/lib/rubocop/cop/platanus/no_render_json.rb +119 -0
- data/lib/rubocop/cop/platanus/pundit_in_application_controller.rb +67 -0
- data/lib/rubocop/cop/platanus_cops.rb +4 -0
- data/lib/rubocop/platanus/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c7bdbf20cbe6ebdb80fc221e98427c0aaf6ce306e0f916eea5d41ddf15a1d61
|
4
|
+
data.tar.gz: 1d8b17010d0875bc096c683444d1d7221b080f07c10d19749db25c8b6db60ebc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afa1eee563a4fb84a2ab075c47c21d0b9a42b92b4ab3f6588e3cb1cd951bc7b39a08c6cf01a2bc2eaf2e56dededd368c4ae78b1f0a56a671cddbc37bbeff2ec1
|
7
|
+
data.tar.gz: ac478f3cd0a18ee955c6c2d03c0d7ca8bfbc18c855393911482dc17d8ceb219e3e01efef45fa3ed22c9e987d0aed8638c68d0b4c5565be441413557e498de9f8
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
4
|
|
5
|
+
### v0.2.0
|
6
|
+
|
7
|
+
Features
|
8
|
+
|
9
|
+
* Add cop Platanus/NoFlashInApi
|
10
|
+
* Add cop Platanus/NoEnumerize
|
11
|
+
* Add cop Platanus/NoRenderJson
|
12
|
+
* Add cop Platanus/PunditInApplicationController
|
13
|
+
|
5
14
|
### v0.1.0
|
6
15
|
|
7
16
|
* Initial release.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rubocop-platanus (0.
|
4
|
+
rubocop-platanus (0.2.0)
|
5
5
|
rubocop (>= 0.89.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -98,6 +98,7 @@ GEM
|
|
98
98
|
unicode-display_width (2.1.0)
|
99
99
|
|
100
100
|
PLATFORMS
|
101
|
+
x86_64-darwin-20
|
101
102
|
x86_64-linux
|
102
103
|
|
103
104
|
DEPENDENCIES
|
@@ -112,4 +113,4 @@ DEPENDENCIES
|
|
112
113
|
rubocop-platanus!
|
113
114
|
|
114
115
|
BUNDLED WITH
|
115
|
-
2.3.
|
116
|
+
2.3.14
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# Rubocop Platanus
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/rubocop-platanus)
|
4
4
|
[](https://app.circleci.com/pipelines/github/platanus/rubocop-platanus)
|
data/config/default.yml
CHANGED
@@ -3,4 +3,36 @@
|
|
3
3
|
Platanus/NoCommand:
|
4
4
|
Description: "Prefer usage of `ActiveJob` instead of `PowerTypes::Command`"
|
5
5
|
Enabled: true
|
6
|
+
Include:
|
7
|
+
- "app/commands/**/*.rb"
|
6
8
|
VersionAdded: "<<next>>"
|
9
|
+
|
10
|
+
Platanus/NoFlashInApi:
|
11
|
+
Description: "Don't use `flash` in api controllers."
|
12
|
+
Enabled: true
|
13
|
+
SafeAutoCorrect: false
|
14
|
+
Include:
|
15
|
+
- "app/controllers/api/**/*.rb"
|
16
|
+
VersionAdded: "<<next>>"
|
17
|
+
|
18
|
+
Platanus/NoEnumerize:
|
19
|
+
Description: "Prefer usage of Rails `enum` instead of `Enumerize`"
|
20
|
+
Enabled: true
|
21
|
+
SafeAutoCorrect: false
|
22
|
+
Include:
|
23
|
+
- "app/models/**/*.rb"
|
24
|
+
VersionAdded: "<<next>>"
|
25
|
+
|
26
|
+
Platanus/NoRenderJson:
|
27
|
+
Description: "Prefer usage of `respond_with` instead of `render json:` to take advantage of `ApiResponder` and `serializers`"
|
28
|
+
Enabled: true
|
29
|
+
Include:
|
30
|
+
- "app/controllers/**/*.rb"
|
31
|
+
VersionAdded: "<<next>>"
|
32
|
+
|
33
|
+
Platanus/PunditInApplicationController:
|
34
|
+
Description: "`Pundit` should be included only in the `Application Controller`"
|
35
|
+
Enabled: true
|
36
|
+
Include:
|
37
|
+
- "app/controllers/**/*.rb"
|
38
|
+
VersionAdded: "0.1.0"
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Platanus
|
6
|
+
# Prefer usage of Rails `enum` instead of `Enumerize`
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# This cop's autocorrection will remove any lines using `extend Enumerize`
|
10
|
+
# and `enumerize :foo, in: [:bar, :baz]` within a file in app/models.
|
11
|
+
# There might be a case where using `enumerize` might be the intended behavior.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # bad
|
15
|
+
# class Foo
|
16
|
+
# extend Enumerize
|
17
|
+
# enumerize :bar, in: [:foo, :bar]
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# class Foo
|
22
|
+
# enum bar: { foo: 0, bar: 1 }
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
class NoEnumerize < Base
|
26
|
+
extend AutoCorrector
|
27
|
+
MSG = 'Use Rails `enum` instead of `enumerize`.'
|
28
|
+
|
29
|
+
# Detect if class extends `Enumerize`
|
30
|
+
def_node_matcher :extend_enumerize?, <<~PATTERN
|
31
|
+
(send nil? :extend (const nil? :Enumerize) ...)
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
# Returns the name and `in:` arguments of the enumerize call
|
35
|
+
def_node_matcher :get_enumerize_args, <<~PATTERN
|
36
|
+
(send nil? :enumerize (sym $_) (
|
37
|
+
hash
|
38
|
+
<
|
39
|
+
(pair (sym :in) (array $...))
|
40
|
+
...
|
41
|
+
>
|
42
|
+
))
|
43
|
+
PATTERN
|
44
|
+
|
45
|
+
def on_send(node)
|
46
|
+
on_extend_enumerize(node)
|
47
|
+
on_enumerize(node)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Detects if class extends `Enumerize`
|
53
|
+
def on_extend_enumerize(node)
|
54
|
+
return unless extend_enumerize?(node)
|
55
|
+
|
56
|
+
add_offense(node) do |corrector|
|
57
|
+
corrector.remove(node)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Detects if class uses `enumerize`. If so, it corrects the code.
|
62
|
+
def on_enumerize(node)
|
63
|
+
enumerize_args = get_enumerize_args(node)
|
64
|
+
return unless enumerize_args
|
65
|
+
|
66
|
+
name, args = enumerize_args
|
67
|
+
args = args.map(&:value)
|
68
|
+
|
69
|
+
add_offense(node) do |corrector|
|
70
|
+
corrector.replace(node, enumerize_correction(name, args))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns the corrected code for `enumerize`
|
75
|
+
def enumerize_correction(name, args)
|
76
|
+
args_string = args.map.with_index do |arg, i|
|
77
|
+
"#{arg}: #{i}"
|
78
|
+
end.join(', ')
|
79
|
+
|
80
|
+
"enum #{name}: { #{args_string} }"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Platanus
|
6
|
+
# Flash shouldn't be used in API controllers.
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# Auto correction will delete any lines using `flash[:type] = 'foo'`. There might be cases
|
10
|
+
# where using flash might be the intended behavior.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# # bad
|
15
|
+
# class Api::Internal::ResourcesController < Api::Internal::BaseController
|
16
|
+
# def show
|
17
|
+
# flash[:notice] = 'Foo'
|
18
|
+
# ...
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
# class Api::Internal::ResourcesController < Api::Internal::BaseController
|
24
|
+
# def show
|
25
|
+
# ...
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
class NoFlashInApi < Base
|
30
|
+
extend AutoCorrector
|
31
|
+
|
32
|
+
MSG = "Don't use `flash` in API controllers."
|
33
|
+
|
34
|
+
def_node_matcher :flash?, <<~PATTERN
|
35
|
+
(send (send nil? :flash) :[]= ...)
|
36
|
+
PATTERN
|
37
|
+
|
38
|
+
def on_send(node)
|
39
|
+
return unless flash?(node)
|
40
|
+
|
41
|
+
add_offense(node) do |corrector|
|
42
|
+
corrector.remove(node)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Platanus
|
6
|
+
# `render json:` shouldn't be used in controllers because it'll skip
|
7
|
+
# the use of ApiResponder and serializers. Use `respond_with` instead.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# render json: { data: @foo }
|
13
|
+
#
|
14
|
+
# # bad
|
15
|
+
# class Api::Internal::ResourcesController < Api::Internal::BaseController
|
16
|
+
# def show
|
17
|
+
# authorization_url = google_srv.generate_authorization_url
|
18
|
+
# respond_with({ authorization_url: authorization_url })
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# class Api::Internal::ResourcesController < Api::Internal::BaseController
|
24
|
+
# def show
|
25
|
+
# hash_response = { data: @foo }
|
26
|
+
# respond_with hash_response
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# # good
|
31
|
+
# respond_with @foo
|
32
|
+
#
|
33
|
+
# # good
|
34
|
+
# # values/resource.rb
|
35
|
+
# class Resource
|
36
|
+
# include ActiveModel::Serialization
|
37
|
+
#
|
38
|
+
# attr_accessor :id, :name
|
39
|
+
#
|
40
|
+
# def initialize(id, name)
|
41
|
+
# @id = id
|
42
|
+
# @name = name
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# # serializers/resource_serializer.rb
|
47
|
+
# class Api::Internal::ResourceSerializer < ActiveModel::Serializer
|
48
|
+
# type :resource
|
49
|
+
# attributes(
|
50
|
+
# :id,
|
51
|
+
# :name
|
52
|
+
# )
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# # controllers/api/internal_resources/resources_controller.rb
|
56
|
+
# class Api::Internal::ResourcesController < Api::Internal::BaseController
|
57
|
+
# def show
|
58
|
+
# respond_with(Resource.new(blog.id, blog.title))
|
59
|
+
# end
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
class NoRenderJson < Base
|
63
|
+
RENDER_JSON_MSG = 'Use `respond_with` instead of `render json:`.'
|
64
|
+
RENDER_HASH_MSG =
|
65
|
+
'Don\'t use `respond_with` with a hash. Use a value and serializer instead.'
|
66
|
+
|
67
|
+
RESTRICT_ON_SEND = %i[render respond_with].freeze
|
68
|
+
|
69
|
+
# Matches if render is called with json
|
70
|
+
def_node_matcher :render_json?, <<~PATTERN
|
71
|
+
(send nil? :render (hash (pair (sym :json) ...) ...))
|
72
|
+
PATTERN
|
73
|
+
|
74
|
+
# Captures the argument of respond_with
|
75
|
+
def_node_matcher :respond_with, <<~PATTERN
|
76
|
+
(send nil? :respond_with $_)
|
77
|
+
PATTERN
|
78
|
+
|
79
|
+
# Matches if node is hash
|
80
|
+
def_node_matcher :is_hash?, '(hash ...)'
|
81
|
+
|
82
|
+
# Captures the variable named of a used variable
|
83
|
+
def_node_matcher :var_name, '(lvar $_)'
|
84
|
+
|
85
|
+
def on_send(node)
|
86
|
+
if render_json?(node)
|
87
|
+
add_offense(node, message: RENDER_JSON_MSG)
|
88
|
+
elsif respond_with_hash?(node)
|
89
|
+
add_offense(node, message: RENDER_HASH_MSG)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Determines if the node corresponds to a call of respond_with
|
94
|
+
# with a hash as it's argument.
|
95
|
+
def respond_with_hash?(node)
|
96
|
+
hash_node = respond_with(node)
|
97
|
+
return true if is_hash?(hash_node)
|
98
|
+
|
99
|
+
var_name = var_name(hash_node)
|
100
|
+
return false if var_name.nil?
|
101
|
+
|
102
|
+
var_is_hash?(node, var_name)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Determines if a variable name corresponds to a hash within it's
|
106
|
+
# most immediate scope.
|
107
|
+
def var_is_hash?(node, var_name)
|
108
|
+
scope = node.parent
|
109
|
+
return false unless scope
|
110
|
+
|
111
|
+
pattern = "`(lvasgn :#{var_name} (hash ...))"
|
112
|
+
matcher = RuboCop::AST::NodePattern.new(pattern)
|
113
|
+
|
114
|
+
matcher.match(scope)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Platanus
|
6
|
+
# Pundit should not be included in specific controllers. Prefer
|
7
|
+
# including it in the ApplicationController instead.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# class ApplicationController < ActionController::Base
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# class FooController < ApplicationController
|
15
|
+
# include Pundit
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # bad
|
19
|
+
# class ApplicationController < ActionController::Base
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# class FooController < ApplicationController
|
23
|
+
# include Pundit::Authorization
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# class ApplicationController < ActionController::Base
|
28
|
+
# include Pundit
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# class FooController < ApplicationController
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# # good
|
35
|
+
# class ApplicationController < ActionController::Base
|
36
|
+
# include Pundit::Authorization
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# class FooController < ApplicationController
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
class PunditInApplicationController < Base
|
43
|
+
MSG = '`Pundit` should be included only in the `ApplicationController`.'
|
44
|
+
|
45
|
+
def_node_matcher :get_include_pundit_node, <<~PATTERN
|
46
|
+
(class _ _ `$(
|
47
|
+
send
|
48
|
+
nil?
|
49
|
+
:include
|
50
|
+
(const {nil? | (const _ :Pundit)} {:Pundit | :Authorization})
|
51
|
+
))
|
52
|
+
PATTERN
|
53
|
+
|
54
|
+
def_node_matcher :application_controller?, <<~PATTERN
|
55
|
+
(class (const nil? :ApplicationController) `(const (const nil? :ActionController) :Base) ...)
|
56
|
+
PATTERN
|
57
|
+
|
58
|
+
def on_class(node)
|
59
|
+
pundit_include_node = get_include_pundit_node(node)
|
60
|
+
return unless pundit_include_node && !application_controller?(node)
|
61
|
+
|
62
|
+
add_offense(pundit_include_node)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -1,3 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'platanus/no_command'
|
4
|
+
require_relative 'platanus/no_flash_in_api'
|
5
|
+
require_relative 'platanus/no_enumerize'
|
6
|
+
require_relative 'platanus/no_render_json'
|
7
|
+
require_relative 'platanus/pundit_in_application_controller'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-platanus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Platanus
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -158,6 +158,10 @@ files:
|
|
158
158
|
- config/default.yml
|
159
159
|
- lib/rubocop-platanus.rb
|
160
160
|
- lib/rubocop/cop/platanus/no_command.rb
|
161
|
+
- lib/rubocop/cop/platanus/no_enumerize.rb
|
162
|
+
- lib/rubocop/cop/platanus/no_flash_in_api.rb
|
163
|
+
- lib/rubocop/cop/platanus/no_render_json.rb
|
164
|
+
- lib/rubocop/cop/platanus/pundit_in_application_controller.rb
|
161
165
|
- lib/rubocop/cop/platanus_cops.rb
|
162
166
|
- lib/rubocop/platanus.rb
|
163
167
|
- lib/rubocop/platanus/inject.rb
|