rubocop-brands_insurance 0.0.2.pre.rc.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b78dfa9d49167cd428caa869e3233539739bf0609ca423c95206d437d0a30491
4
+ data.tar.gz: edd592a746d2ea5396a5585ce01dd504698fba5767f55ae5f238ce0ae9541468
5
+ SHA512:
6
+ metadata.gz: 9576f39c77c22ac92247b9f3fe45e8a48298570c6c125bee83cc45aa0d4367ccd37410ddd5b975202a69ef664d75d4bd1252f42d26266b4874d1db7d20cb32cc
7
+ data.tar.gz: fd679b7562290fc20b46c61d7d4cd29d0d7bd0ae7b818e25398aa35c019cca50d55c658a99ad88085ef9808b3c589bbcb9fc393577b9af8b33286d0a7bd19699
data/README.adoc ADDED
@@ -0,0 +1,50 @@
1
+ = Rubocop::BrandsInsurance
2
+
3
+ Gem for custom rubocop rules for BrandsInsurance
4
+
5
+ Welcome to your new gem!
6
+ In this directory, you'll find the files you need to be able to package up your Ruby library into a gem.
7
+ Put your Ruby code in the file ``lib/rubocop/brands_insurance``.
8
+ To experiment with that code, run
9
+ ``bin/console`` for an interactive prompt.
10
+
11
+ TODO: Delete this and the text above, and describe your gem
12
+
13
+ == Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ [source,ruby]
18
+ ----
19
+ gem 'rubocop-brands_insurance', require: false
20
+ ----
21
+
22
+ And then execute:
23
+
24
+ $ bundle install
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install rubocop-brands_insurance
29
+
30
+ == Usage
31
+
32
+ Add ``BrandsInsurance/*`` cops to your ``.rubocop.yml`` config file
33
+
34
+ [source,yaml]
35
+ ----
36
+ BrandsInsurance/Style/DisallowedMethods:
37
+ Enabled: true
38
+ ----
39
+
40
+ == Departments
41
+
42
+ * xref:./docs/cops/style/README.adoc[``Style``]
43
+
44
+ == Contributing
45
+
46
+ See xref:./CONTRIBUTING.adoc[CONTRIBUTING] for how to add your own rule
47
+
48
+ == Changelog
49
+
50
+ See xref:./CHANGELOG.adoc[CHANGELOG] see see changes
@@ -0,0 +1,4 @@
1
+ BrandsInsurance/Style/DisallowedMethods:
2
+ Description: 'Disallows the usage of `#abort` and `#tap` methods'
3
+ Enabled: pending
4
+ VersionAdded: '<<next>>'
@@ -0,0 +1,7 @@
1
+ = Style
2
+
3
+ Style cops check for stylistic consistency of your code
4
+
5
+ == Cops
6
+
7
+ * xref:./disallowed_methods/README.adoc[``Style/DisallowedMethods``]
@@ -0,0 +1,28 @@
1
+ = ``Style/DisallowedMethods``
2
+
3
+ == Description
4
+
5
+ Certain methods should not be used
6
+
7
+ == Examples
8
+
9
+ [source,ruby]
10
+ ----
11
+ # Bad (Don't use `tap`)
12
+ tap do
13
+ end
14
+
15
+ # Bad (Don't use `abort`)
16
+ abort
17
+
18
+ # Good (Use `raise` instead of `abort`)
19
+ raise
20
+ ----
21
+
22
+ == Configurable Attributes
23
+
24
+ There are no configurable attributes
25
+
26
+ == References
27
+
28
+ https://github.com/BrandsInsurance/expert-chainsaw/issues/434
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The original code is from https://github.com/rubocop/rubocop-rspec/blob/master/lib/rubocop/rspec/inject.rb
4
+ # See https://github.com/rubocop/rubocop-rspec/blob/master/MIT-LICENSE.md
5
+ module RuboCop
6
+ module BrandsInsurance
7
+ # Because RuboCop doesn't yet support plugins, we have to monkey patch in a
8
+ # bit of our configuration.
9
+ module Inject
10
+ def self.defaults!
11
+ path = CONFIG_DEFAULT.to_s
12
+ hash = ConfigLoader.__send__(:load_yaml_configuration, path)
13
+ config = Config.new(hash, path).tap(&:make_excludes_absolute)
14
+ puts("configuration from #{path}") if ConfigLoader.debug?
15
+ config = ConfigLoader.merge_with_default(config, path)
16
+ ConfigLoader.instance_variable_set(:@default_configuration, config)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module BrandsInsurance
5
+ VERSION = '0.0.2-rc.1'
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'brands_insurance/version'
4
+ require 'yaml'
5
+
6
+ module RuboCop
7
+ module BrandsInsurance
8
+ class Error < StandardError; end
9
+ # Your code goes here...
10
+ PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze
11
+ CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze
12
+ CONFIG = ::YAML.safe_load(CONFIG_DEFAULT.read).freeze
13
+
14
+ private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT)
15
+ end
16
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module BrandsInsurance
6
+ class Generator
7
+ class CopReadmeInjector < DeptReadmeInjector
8
+ TEMPLATE =
9
+ '* xref:./%<cop_folder>s/README.adoc[``%<department>s/%<cop>s``]'
10
+
11
+ # :nodoc:
12
+ def initialize(badge:, **kwargs)
13
+ super(badge: badge, **kwargs)
14
+
15
+ @cop = badge.cop_name
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :cop
21
+
22
+ def new_readme_entry
23
+ format(TEMPLATE, {
24
+ department_folder: snake_case(department),
25
+ cop_folder: snake_case(cop),
26
+ department: department,
27
+ cop: cop
28
+ })
29
+ end
30
+
31
+ def line_is_good?(line)
32
+ return true if super
33
+
34
+ matches = line.match(target_regex)
35
+ return false if matches.nil?
36
+
37
+ department == matches[:department] && cop < matches[:cop]
38
+ end
39
+
40
+ def target_regex
41
+ %r{\* xref:\./docs/cops/[a-z_]+/[a-z_]+/README\.adoc\[``(?<department>[a-zA-Z_]+)/(?<cop>[a-zA-Z_]+)``\]}
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module BrandsInsurance
6
+ class Generator
7
+ class DeptReadmeInjector
8
+ TEMPLATE = '* xref:./docs/cops/%<department_folder>s/README.adoc[``%<department>s``]'
9
+
10
+ # :nodoc:
11
+ def initialize(readme_file_path:, badge:, department:)
12
+ @readme_file_path = readme_file_path
13
+ @badge = badge
14
+ @department = department
15
+ @output = output
16
+ end
17
+
18
+ # :nodoc:
19
+ def inject
20
+ target_line = find_target_line
21
+ if target_line
22
+ readme_entries.insert(target_line, "#{new_readme_entry}\n")
23
+ else
24
+ readme_entries.push("#{new_readme_entry}")
25
+ end
26
+
27
+ File.write(readme_file_path, readme_entries.join(''))
28
+
29
+ yield if block_given?
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :readme_file_path, :badge, :department, :output
35
+
36
+ def readme_entries
37
+ @readme_entries ||= File.readlines(readme_file_path)
38
+ end
39
+
40
+ def new_readme_entry
41
+ format(TEMPLATE, {
42
+ department_folder: snake_case(department),
43
+ department: department
44
+ })
45
+ end
46
+
47
+ def find_target_line
48
+ readme_entries.find.with_index do |line, index|
49
+ return index if line_is_good?(line)
50
+ end
51
+
52
+ return nil
53
+ end
54
+
55
+ def line_is_good?(line)
56
+ matches = line.match(target_regex)
57
+ return false if matches.nil?
58
+
59
+ department < line.match(target_regex)[:department]
60
+ end
61
+
62
+ def target_regex
63
+ %r{\* xref:\./docs/cops/[a-z_]+/README\.adoc\[``(?<department>[a-zA-Z_]+)``\]}
64
+ end
65
+
66
+ def snake_case(camel_case_string)
67
+ camel_case_string
68
+ .gsub('RSpec', 'Rspec')
69
+ .gsub(%r{([^A-Z/])([A-Z]+)}, '\1_\2')
70
+ .gsub(%r{([A-Z])([A-Z][^A-Z\d/]+)}, '\1_\2')
71
+ .downcase
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,239 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './generator/dept_readme_injector'
4
+ require_relative './generator/cop_readme_injector'
5
+
6
+ module RuboCop
7
+ module Cop
8
+ module BrandsInsurance
9
+ class Generator
10
+ COP_DOC = <<~RUBY
11
+ # TODO: Write cop description and example of bad / good code. For every
12
+ # `SupportedStyle` and unique configuration, there needs to be examples.
13
+ # Examples must have valid Ruby syntax. Do not use upticks.
14
+ #
15
+ # @safety
16
+ # Delete this section if the cop is not unsafe (`Safe: false` or
17
+ # `SafeAutoCorrect: false`), or use it to explain how the cop is
18
+ # unsafe.
19
+ #
20
+ # @example EnforcedStyle: bar (default)
21
+ # # Description of the `bar` style.
22
+ #
23
+ # # bad
24
+ # bad_bar_method
25
+ #
26
+ # # bad
27
+ # bad_bar_method(args)
28
+ #
29
+ # # good
30
+ # good_bar_method
31
+ #
32
+ # # good
33
+ # good_bar_method(args)
34
+ #
35
+ # @example EnforcedStyle: foo
36
+ # # Description of the `foo` style.
37
+ #
38
+ # # bad
39
+ # bad_foo_method
40
+ #
41
+ # # bad
42
+ # bad_foo_method(args)
43
+ #
44
+ # # good
45
+ # good_foo_method
46
+ #
47
+ # # good
48
+ # good_foo_method(args)
49
+ #
50
+ RUBY
51
+ SOURCE_TEMPLATE = <<~RUBY
52
+ # frozen_string_literal: true
53
+
54
+ module RuboCop
55
+ module Cop
56
+ module %<department>s
57
+ class %<cop_name>s < Base
58
+ # TODO: Implement the cop in here.
59
+ #
60
+ # In many cases, you can use a node matcher for matching node pattern.
61
+ # See https://github.com/rubocop/rubocop-ast/blob/master/lib/rubocop/ast/node_pattern.rb
62
+ #
63
+ # For example
64
+ MSG = 'Use `#good_method` instead of `#bad_method`.'
65
+
66
+ # TODO: Don't call `on_send` unless the method name is in this list
67
+ # If you don't need `on_send` in the cop you created, remove it.
68
+ RESTRICT_ON_SEND = %%i[bad_method].freeze
69
+
70
+ # @!method bad_method?(node)
71
+ def_node_matcher :bad_method?, <<~PATTERN
72
+ (send nil? :bad_method ...)
73
+ PATTERN
74
+
75
+ def on_send(node)
76
+ return unless bad_method?(node)
77
+
78
+ add_offense(node)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ RUBY
85
+ README_ADDED_MESSAGE =
86
+ '[modify] A link for the %<dept_vs_cop>s has been added into ' \
87
+ '%<readme_file_path>s.'
88
+
89
+ DEPT_README_TEMPLATE = <<~ADOC
90
+ = %<department>s
91
+
92
+ Describe the department here
93
+
94
+ == Cops
95
+
96
+ ADOC
97
+ COP_README_TEMPLATE = <<~ADOC
98
+ = ``%<department>s/%<cop_name>s``
99
+
100
+ == Description
101
+
102
+ Add a description here
103
+
104
+ == Examples
105
+
106
+ [source,ruby]
107
+ ----
108
+ # Bad
109
+ # Add a bad example here
110
+
111
+ # Good
112
+ # Add a good example here
113
+ ----
114
+
115
+ == Configurable Attributes
116
+
117
+ |===
118
+ |Name |Default value |Configurable values
119
+
120
+ |Max
121
+ |120
122
+ |Integer
123
+
124
+ |===
125
+
126
+ == References
127
+
128
+ https://github.com/BrandsInsurance/expert-chainsaw/issues
129
+ ADOC
130
+
131
+ def initialize(name, output: $stdout)
132
+ name = ['BrandsInsurance', name].join('/') unless name.start_with?('BrandsInsurance/')
133
+
134
+ unless name.count('/') == 2
135
+ raise(
136
+ [
137
+ 'You must provide a single department under BrandsInsurance i.e. BrandsInsurance/Department/CopName',
138
+ 'or Department/CopName'
139
+ ].join(' ')
140
+ )
141
+ end
142
+
143
+ @base_gen = RuboCop::Cop::Generator.new(name, output: output)
144
+ end
145
+
146
+ # Calls methods in the base class
147
+ #
148
+ # @return [*]
149
+ #
150
+ def method_missing(...)
151
+ @base_gen.__send__(...)
152
+ end
153
+
154
+ # `self` responds to `method_name` if `@base_gen` does
155
+ #
156
+ def respond_to_missing?(method_name, include_private = false)
157
+ @base_gen.respond_to?(method_name, include_private)
158
+ end
159
+
160
+ def write_dept_readme
161
+ return if File.exists?(dept_docs_path)
162
+
163
+ write_unless_file_exists(dept_docs_path, generated_dept_docs)
164
+ end
165
+
166
+ def write_cop_readme
167
+ write_unless_file_exists(docs_path, generated_cop_docs)
168
+ end
169
+
170
+ def inject_dept_readme(readme_file_path: 'README.adoc')
171
+ # Add this dept to base readme if not already there
172
+ injector = DeptReadmeInjector.new(
173
+ readme_file_path: readme_file_path,
174
+ badge: badge,
175
+ department: department
176
+ )
177
+
178
+ injector.inject do
179
+ output.puts(format(README_ADDED_MESSAGE, readme_file_path: readme_file_path, dept_vs_cop: 'department'))
180
+ end
181
+ end
182
+
183
+ def inject_cop_readme(readme_file_path: dept_docs_path)
184
+ # Add this cop to the dept readme
185
+ injector = CopReadmeInjector.new(
186
+ readme_file_path: readme_file_path,
187
+ badge: badge,
188
+ department: department
189
+ )
190
+
191
+ injector.inject do
192
+ output.puts(format(README_ADDED_MESSAGE, readme_file_path: readme_file_path, dept_vs_cop: 'cop'))
193
+ end
194
+ end
195
+
196
+ private
197
+
198
+ def department
199
+ badge.department_name.gsub('BrandsInsurance/', '')
200
+ end
201
+
202
+ def generated_dept_docs
203
+ generate_readme(DEPT_README_TEMPLATE)
204
+ end
205
+
206
+ def generated_cop_docs
207
+ generate_readme(COP_README_TEMPLATE)
208
+ end
209
+
210
+ def generate_readme(template)
211
+ format(template, {
212
+ department: department,
213
+ cop_name: badge.cop_name,
214
+ cop_folder: snake_case(badge.cop_name.to_s)
215
+ })
216
+ end
217
+
218
+ def dept_docs_path
219
+ File.join(
220
+ 'docs',
221
+ 'cops',
222
+ snake_case(department),
223
+ 'README.adoc'
224
+ )
225
+ end
226
+
227
+ def docs_path
228
+ File.join(
229
+ 'docs',
230
+ 'cops',
231
+ snake_case(department),
232
+ "#{snake_case(badge.cop_name.to_s)}",
233
+ 'README.adoc'
234
+ )
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module BrandsInsurance
6
+ module Style
7
+ # @example EnforcedStyle: foo
8
+ # # Description of the `foo` style.
9
+ #
10
+ # # bad
11
+ # abort
12
+ #
13
+ # # bad
14
+ # abort(args)
15
+ #
16
+ # # bad
17
+ # tap {}
18
+ #
19
+ # # bad
20
+ # tap do
21
+ # end
22
+ #
23
+ # # good
24
+ # raise
25
+ #
26
+ # # good
27
+ # raise(args)
28
+ #
29
+ class DisallowedMethods < RuboCop::Cop::Base
30
+ # In many cases, you can use a node matcher for matching node pattern.
31
+ # See https://github.com/rubocop/rubocop-ast/blob/master/lib/rubocop/ast/node_pattern.rb
32
+ #
33
+ # For example
34
+ MESSAGES = {
35
+ abort: 'Use `#raise` instead of `#abort`.',
36
+ tap: 'Do not use `#tap`'
37
+ }
38
+
39
+ # `on_send` will only be called if the method name is in this list
40
+ RESTRICT_ON_SEND = %i[abort tap].freeze
41
+
42
+ # @!method using_abort?(node)
43
+ def_node_matcher :using_abort?, <<~PATTERN
44
+ (send nil? :abort ...)
45
+ PATTERN
46
+
47
+ # @!method using_tap?(node)
48
+ def_node_matcher :using_tap?, <<~PATTERN
49
+ (send nil? :tap ...)
50
+ PATTERN
51
+
52
+ # :nodoc:
53
+ def on_send(node)
54
+ message =
55
+ if using_abort?(node)
56
+ :abort
57
+ elsif using_tap?(node)
58
+ :tap
59
+ end
60
+
61
+ return if message.nil?
62
+
63
+ add_offense(node, message: MESSAGES.fetch(message))
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'brands_insurance/style/disallowed_methods'
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+
5
+ require_relative 'rubocop/brands_insurance'
6
+ require_relative 'rubocop/cop/brands_insurance/generator'
7
+ require_relative 'rubocop/brands_insurance/inject'
8
+ require_relative 'rubocop/brands_insurance/version'
9
+
10
+ RuboCop::BrandsInsurance::Inject.defaults!
11
+
12
+ require_relative 'rubocop/cop/brands_insurance_cops'
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubocop-brands_insurance
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2.pre.rc.1
5
+ platform: ruby
6
+ authors:
7
+ - Brands Insurance
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-03-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rubocop
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.43'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.43'
27
+ description:
28
+ email:
29
+ - documents@brandsinsurance.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - README.adoc
35
+ - config/default.yml
36
+ - docs/cops/style/README.adoc
37
+ - docs/cops/style/disallowed_methods/README.adoc
38
+ - lib/rubocop-brands_insurance.rb
39
+ - lib/rubocop/brands_insurance.rb
40
+ - lib/rubocop/brands_insurance/inject.rb
41
+ - lib/rubocop/brands_insurance/version.rb
42
+ - lib/rubocop/cop/brands_insurance/generator.rb
43
+ - lib/rubocop/cop/brands_insurance/generator/cop_readme_injector.rb
44
+ - lib/rubocop/cop/brands_insurance/generator/dept_readme_injector.rb
45
+ - lib/rubocop/cop/brands_insurance/style/disallowed_methods.rb
46
+ - lib/rubocop/cop/brands_insurance_cops.rb
47
+ homepage: https://github.com/BrandsInsurance/expert-chainsaw/
48
+ licenses: []
49
+ metadata:
50
+ homepage_uri: https://github.com/BrandsInsurance/expert-chainsaw/
51
+ source_code_uri: https://github.com/BrandsInsurance/expert-chainsaw/plugins/rubocop/brandsinsurance
52
+ changelog_uri: https://github.com/BrandsInsurance/expert-chainsaw/plugins/rubocop/brandsinsurance/CHANGELOG.adoc
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 3.0.1
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">"
65
+ - !ruby/object:Gem::Version
66
+ version: 1.3.1
67
+ requirements: []
68
+ rubygems_version: 3.2.15
69
+ signing_key:
70
+ specification_version: 4
71
+ summary: Custom cops for BrandsInsurance
72
+ test_files: []