rubocop-mdsol 0.2.0 → 0.3.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 +4 -0
- data/Gemfile +3 -0
- data/README.md +17 -0
- data/Rakefile +29 -0
- data/config/default.yml +9 -0
- data/lib/rubocop/cop/mdsol/log_with_data.rb +81 -0
- data/lib/rubocop/cop/mdsol/unless_not_equal.rb +60 -0
- data/lib/rubocop/cop/mdsol_cops.rb +2 -0
- data/lib/rubocop/mdsol/inject.rb +20 -0
- data/lib/rubocop/mdsol/version.rb +7 -0
- data/lib/rubocop/mdsol.rb +15 -0
- data/lib/rubocop-mdsol.rb +11 -0
- data/rubocop-mdsol.gemspec +11 -11
- metadata +56 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ea1fee9117692bb17d96ebfbf59955dbfd329010bf8802a65d3f45b89f238f5
|
4
|
+
data.tar.gz: caabfe16c4b05113edec4ace5265e7d00dd70c539e66a6a0ef4cf50e0e31bb8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f0ddcd460d42ad310c8dd794eba171fa5895ecd6778def44faf6d4cf9dbe53d2aad2561cb3664deb52d16b08abe0be7881c6a8feb3a8a9b4fe328029bdeac0f
|
7
|
+
data.tar.gz: ea26682188a2187fcbb4760a6d32d70215f625e5e38c753220ad6daefeea9412c56b79b663dba36c95fb30067dbbcd0b82dc21f5a5b01917698f067e52c4b5bb
|
data/CHANGELOG.md
CHANGED
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -60,6 +60,23 @@ inherit_gem:
|
|
60
60
|
# your customizations here...
|
61
61
|
```
|
62
62
|
|
63
|
+
### Custom Cops
|
64
|
+
|
65
|
+
To activate the custom cops (`mdsol/*`) shipped with this Gem:
|
66
|
+
|
67
|
+
```yaml
|
68
|
+
require: rubocop-mdsol
|
69
|
+
|
70
|
+
# or using the array notation to specify multiple extensions:
|
71
|
+
|
72
|
+
require:
|
73
|
+
- rubocop-mdsol
|
74
|
+
- rubocop-rails
|
75
|
+
```
|
76
|
+
|
77
|
+
All cops are located under
|
78
|
+
[`lib/rubocop/cop/mdsol`](lib/rubocop/cop/mdsol) and contain examples/documentation.
|
79
|
+
|
63
80
|
|
64
81
|
## Recommended customizations
|
65
82
|
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
task default: %i[]
|
5
|
+
|
6
|
+
require "rspec/core/rake_task"
|
7
|
+
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
9
|
+
spec.pattern = FileList["spec/**/*_spec.rb"]
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Generate a new cop with a template"
|
13
|
+
task :new_cop, [:cop] do |_task, args|
|
14
|
+
require "rubocop"
|
15
|
+
|
16
|
+
cop_name = args.fetch(:cop) do
|
17
|
+
warn "usage: bundle exec rake new_cop[Department/Name]"
|
18
|
+
exit!
|
19
|
+
end
|
20
|
+
|
21
|
+
generator = RuboCop::Cop::Generator.new(cop_name)
|
22
|
+
|
23
|
+
generator.write_source
|
24
|
+
generator.write_spec
|
25
|
+
generator.inject_require(root_file_path: "lib/rubocop/cop/mdsol_cops.rb")
|
26
|
+
generator.inject_config(config_file_path: "config/default.yml")
|
27
|
+
|
28
|
+
puts generator.todo
|
29
|
+
end
|
data/config/default.yml
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Mdsol
|
6
|
+
# Favor the logger.<level>_with_data method for structured logging.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad - string interpolations exceed the threshold (configurable via AllowedStringInterpolations setting)
|
10
|
+
# Rails.logger.info("a message with more than 2 interpolations: #{foo} #{bar} #{baz}")
|
11
|
+
#
|
12
|
+
# # bad - string interpolation contains Enumerable methods (:map, :collect)
|
13
|
+
# Rails.logger.info("Deleted the following records: #{records.map(&:id)}")
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# Rails.logger.info("a message")
|
17
|
+
#
|
18
|
+
# # good - string interpolations are within the threshold (configurable via AllowedStringInterpolations setting)
|
19
|
+
# Rails.logger.info("a message with 2 interpolations: #{foo} #{bar}")
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# Rails.logger.info_with_data("Created the record", record_id: record.id, status: status)
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# Rails.logger.info_with_data("Deleted the following records", record_ids: results.records.map(&:id))
|
26
|
+
class LogWithData < Base
|
27
|
+
MSG = "Use `logger.%<method>s_with_data(msg, data_hash)` instead. See https://github.com/mdsol/astinus#using-context-data-logging"
|
28
|
+
|
29
|
+
RESTRICT_ON_SEND = %i[logger debug info warn error].freeze
|
30
|
+
FORBIDDEN_ENUMERABLE_METHODS = %i[map collect].freeze
|
31
|
+
DEFAULT_STRING_INTERPOLATION_THRESHOLD = 2
|
32
|
+
|
33
|
+
# AST for code: `Rails.logger.debug("study creation request #{request} was status #{status}")`
|
34
|
+
# (send
|
35
|
+
# (send
|
36
|
+
# (const nil :Rails) :logger) :debug
|
37
|
+
# (dstr
|
38
|
+
# (str "study creation request ")
|
39
|
+
# (begin
|
40
|
+
# (send nil :request))
|
41
|
+
# (str " was status ")
|
42
|
+
# (begin
|
43
|
+
# (send nil :status))))
|
44
|
+
def_node_matcher :logger_with_interpolation, <<~PATTERN
|
45
|
+
(send (send (const nil? $_) :logger) $_ $(dstr ...))
|
46
|
+
PATTERN
|
47
|
+
|
48
|
+
def on_send(node)
|
49
|
+
logger_with_interpolation(node) do |logger_owner, log_method, log_message|
|
50
|
+
return unless registered_logger_owners.include?(logger_owner.to_s)
|
51
|
+
|
52
|
+
if interpoloations_exceed_threshold?(log_message) || contain_forbidden_enumerable_method?(log_message)
|
53
|
+
msg = format(MSG, method: log_method.to_s)
|
54
|
+
add_offense(node, message: msg)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def registered_logger_owners
|
62
|
+
@registered_logger_owners ||= (["Rails"] + cop_config["LoggerOwners"].to_a).uniq
|
63
|
+
end
|
64
|
+
|
65
|
+
def interpoloations_exceed_threshold?(log_message_node)
|
66
|
+
log_message_node.child_nodes.count { |node| node.type == :begin } > string_interpolations_threshold
|
67
|
+
end
|
68
|
+
|
69
|
+
def string_interpolations_threshold
|
70
|
+
cop_config["AllowedStringInterpolations"] || DEFAULT_STRING_INTERPOLATION_THRESHOLD
|
71
|
+
end
|
72
|
+
|
73
|
+
def contain_forbidden_enumerable_method?(log_message_node)
|
74
|
+
log_message_node.each_descendant.any? do |descedant|
|
75
|
+
descedant.send_type? && FORBIDDEN_ENUMERABLE_METHODS.include?(descedant.method_name)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Mdsol
|
6
|
+
# Avoid double negative condition.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# do_something unless a != b
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# do_something if a == b
|
14
|
+
#
|
15
|
+
# Credit to Warut: https://github.com/mdsol/tenjin/pull/621#discussion_r748106992
|
16
|
+
class UnlessNotEqual < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
|
19
|
+
MSG = "Avoid double negative. Write `%<correction>s` instead."
|
20
|
+
|
21
|
+
# AST for: `do_something unless a != b`
|
22
|
+
# (if
|
23
|
+
# (send
|
24
|
+
# (send nil :a) :!=
|
25
|
+
# (send nil :b)) nil
|
26
|
+
# (send nil :do_something))
|
27
|
+
def_node_matcher :unless_not_equal_match, <<~PATTERN
|
28
|
+
(if $(send $(...) :!= $(...)) ...)
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def on_if(node)
|
32
|
+
return if node.ternary? || node.if? || node.elsif?
|
33
|
+
|
34
|
+
unless_not_equal_match(node) do |unless_body_node, left, right|
|
35
|
+
correction = "if #{left.source} == #{right.source}"
|
36
|
+
msg = format(MSG, correction: correction)
|
37
|
+
range = range_with_unless_modifier(unless_body_node)
|
38
|
+
|
39
|
+
add_offense(range, message: msg) do |corrector|
|
40
|
+
corrector.replace(range, correction)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def range_with_unless_modifier(unless_body_node)
|
48
|
+
leading_unless = "unless "
|
49
|
+
expand_range_to_left_by(unless_body_node, leading_unless.size)
|
50
|
+
end
|
51
|
+
|
52
|
+
def expand_range_to_left_by(node, length)
|
53
|
+
source_range = node.source_range
|
54
|
+
source_buffer = source_range.source_buffer
|
55
|
+
Parser::Source::Range.new(source_buffer, source_range.begin_pos - length, source_range.end_pos)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -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 Mdsol
|
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,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "mdsol/version"
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Mdsol
|
7
|
+
class Error < StandardError; end
|
8
|
+
# Your code goes here...
|
9
|
+
PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze
|
10
|
+
CONFIG_DEFAULT = PROJECT_ROOT.join("config", "default.yml").freeze
|
11
|
+
CONFIG = YAML.safe_load(CONFIG_DEFAULT.read).freeze
|
12
|
+
|
13
|
+
private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT)
|
14
|
+
end
|
15
|
+
end
|
data/rubocop-mdsol.gemspec
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "lib/rubocop/mdsol/version"
|
4
|
+
|
3
5
|
Gem::Specification.new do |spec|
|
4
6
|
spec.name = "rubocop-mdsol"
|
5
|
-
spec.version =
|
7
|
+
spec.version = RuboCop::Mdsol::VERSION
|
6
8
|
spec.authors = ["Team Æ", "Team 10"]
|
7
9
|
spec.email = ["ae@mdsol.com", "team10@mdsol.com"]
|
8
10
|
spec.license = "MIT"
|
@@ -13,17 +15,15 @@ Gem::Specification.new do |spec|
|
|
13
15
|
"changelog_uri" => "https://github.com/mdsol/rubocop-mdsol/blob/develop/CHANGELOG.md"
|
14
16
|
}
|
15
17
|
|
16
|
-
spec.files
|
17
|
-
|
18
|
-
|
19
|
-
"README.md",
|
20
|
-
"rubocop-mdsol.gemspec",
|
21
|
-
"rubocop-rails.yml",
|
22
|
-
"rubocop-rspec.yml",
|
23
|
-
"rubocop.yml"
|
24
|
-
]
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
|
+
f.match(/^(\.|bin|spec)/)
|
20
|
+
end
|
25
21
|
|
26
|
-
spec.required_ruby_version = ">= 2.
|
22
|
+
spec.required_ruby_version = ">= 2.7.0"
|
23
|
+
spec.require_paths = ["lib"]
|
27
24
|
|
28
25
|
spec.add_dependency "rubocop", "~> 1.0"
|
26
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.11"
|
28
|
+
spec.add_development_dependency "rubocop-rspec", "~> 2.11"
|
29
29
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-mdsol
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Team Æ
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-
|
12
|
+
date: 2022-06-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rubocop
|
@@ -25,6 +25,48 @@ dependencies:
|
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '1.0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '13.0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '13.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '3.11'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '3.11'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rubocop-rspec
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '2.11'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '2.11'
|
28
70
|
description:
|
29
71
|
email:
|
30
72
|
- ae@mdsol.com
|
@@ -34,8 +76,18 @@ extensions: []
|
|
34
76
|
extra_rdoc_files: []
|
35
77
|
files:
|
36
78
|
- CHANGELOG.md
|
79
|
+
- Gemfile
|
37
80
|
- MIT-LICENSE
|
38
81
|
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- config/default.yml
|
84
|
+
- lib/rubocop-mdsol.rb
|
85
|
+
- lib/rubocop/cop/mdsol/log_with_data.rb
|
86
|
+
- lib/rubocop/cop/mdsol/unless_not_equal.rb
|
87
|
+
- lib/rubocop/cop/mdsol_cops.rb
|
88
|
+
- lib/rubocop/mdsol.rb
|
89
|
+
- lib/rubocop/mdsol/inject.rb
|
90
|
+
- lib/rubocop/mdsol/version.rb
|
39
91
|
- rubocop-mdsol.gemspec
|
40
92
|
- rubocop-rails.yml
|
41
93
|
- rubocop-rspec.yml
|
@@ -54,14 +106,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
106
|
requirements:
|
55
107
|
- - ">="
|
56
108
|
- !ruby/object:Gem::Version
|
57
|
-
version: 2.
|
109
|
+
version: 2.7.0
|
58
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
111
|
requirements:
|
60
112
|
- - ">="
|
61
113
|
- !ruby/object:Gem::Version
|
62
114
|
version: '0'
|
63
115
|
requirements: []
|
64
|
-
rubygems_version: 3.
|
116
|
+
rubygems_version: 3.3.15
|
65
117
|
signing_key:
|
66
118
|
specification_version: 4
|
67
119
|
summary: Base RuboCop configuration files for Ruby projects at Medidata
|