rubocop-platanus 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/rubocop-platanus.svg)](https://badge.fury.io/rb/rubocop-platanus)
|
4
4
|
[![CircleCI](https://circleci.com/gh/platanus/rubocop-platanus.svg?style=shield)](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
|