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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a03dfa4de53bd8b6ecc894167346f22ae13d475c5388990d014b8cf910a36aa7
4
- data.tar.gz: aa8b77d809a7c927feb85fbc2611bca678025243e2997a98aea81bc25fa25d68
3
+ metadata.gz: 1c7bdbf20cbe6ebdb80fc221e98427c0aaf6ce306e0f916eea5d41ddf15a1d61
4
+ data.tar.gz: 1d8b17010d0875bc096c683444d1d7221b080f07c10d19749db25c8b6db60ebc
5
5
  SHA512:
6
- metadata.gz: 1f8e068755dca01d916faa1e80696d4a7e169d805829a0c62f3fba93f30ca76e55208ba70116d844d12c0c84d71ebf02d0cedc70f90658a0fc49624471ebcdeb
7
- data.tar.gz: 80a86b5d5706bb9306c14a10b030f6500fce2b7f66e26c30247419f2b16527ab7e7e891b235c251f2554fd4583798267af01438d225045f9b1dd679644aa321c
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.1.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.11
116
+ 2.3.14
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Test Gem
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'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Platanus
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
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.1.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-04-22 00:00:00.000000000 Z
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