rubocop-ordered_methods 0.8 → 0.10
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/.github/workflows/main.yml +46 -0
- data/.rubocop.yml +16 -1
- data/.travis.yml +1 -1
- data/CHANGELOG.md +17 -0
- data/Gemfile +5 -0
- data/README.md +34 -2
- data/config/default.yml +1 -0
- data/lib/rubocop/cop/correctors/ordered_methods_corrector.rb +46 -4
- data/lib/rubocop/cop/layout/ordered_methods.rb +47 -19
- data/lib/rubocop/cop/qualifier_node_matchers.rb +9 -2
- data/rubocop-ordered_methods.gemspec +3 -5
- metadata +7 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c43226dde578a4844ba7c579a7fa5dfb52f05dce2e84d9a68f1e250e272d4e58
|
4
|
+
data.tar.gz: 636542d7c4be5982d3424703ba2062c72c4fdbfcf4f289a5b593050b68c16969
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1eced8a7bb0e4a33bf58cae6b0b0d90fd9814318635689450ee34646905a5a41fbd97189c51d9763706f307d4ed4c3032e3eb02af2aa5ce79c373f12bd5f1019
|
7
|
+
data.tar.gz: 4c528b7368611c20b2ab790f28502f3c44e4e6546bcbff35b199c749932583bdea36cc5d441e598efb7b7e199b63fbac97f50a6534b206052f60474ebe24147a
|
@@ -0,0 +1,46 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
push:
|
6
|
+
branches:
|
7
|
+
- master
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
rspec:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
strategy:
|
13
|
+
matrix:
|
14
|
+
ruby:
|
15
|
+
- "2.7"
|
16
|
+
- "3.0"
|
17
|
+
- "3.1"
|
18
|
+
- "3.2"
|
19
|
+
|
20
|
+
name: "Ruby ${{ matrix.ruby }}: run rspec"
|
21
|
+
steps:
|
22
|
+
- uses: actions/checkout@v3
|
23
|
+
- uses: ruby/setup-ruby@v1
|
24
|
+
with:
|
25
|
+
ruby-version: "${{ matrix.ruby }}"
|
26
|
+
bundler-cache: true
|
27
|
+
- run: bundle exec rspec
|
28
|
+
|
29
|
+
rubocop:
|
30
|
+
runs-on: ubuntu-latest
|
31
|
+
strategy:
|
32
|
+
matrix:
|
33
|
+
ruby:
|
34
|
+
- "2.7"
|
35
|
+
- "3.0"
|
36
|
+
- "3.1"
|
37
|
+
- "3.2"
|
38
|
+
|
39
|
+
name: "Ruby ${{ matrix.ruby }}: run rubocop"
|
40
|
+
steps:
|
41
|
+
- uses: actions/checkout@v3
|
42
|
+
- uses: ruby/setup-ruby@v1
|
43
|
+
with:
|
44
|
+
ruby-version: "${{ matrix.ruby }}"
|
45
|
+
bundler-cache: true
|
46
|
+
- run: bundle exec rubocop
|
data/.rubocop.yml
CHANGED
@@ -5,7 +5,16 @@ require: rubocop-ordered_methods
|
|
5
5
|
AllCops:
|
6
6
|
NewCops: enable
|
7
7
|
SuggestExtensions: false
|
8
|
-
TargetRubyVersion: 2.
|
8
|
+
TargetRubyVersion: 2.7
|
9
|
+
|
10
|
+
# Subtle, left to author's discretion. In a long method with many guard clauses,
|
11
|
+
# a blank line may help. But, in a short method, especially with only a single
|
12
|
+
# guard clause, a blank line can be disruptive.
|
13
|
+
Layout/EmptyLineAfterGuardClause:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Layout/LineEndStringConcatenationIndentation:
|
17
|
+
EnforcedStyle: indented
|
9
18
|
|
10
19
|
Metrics/BlockLength:
|
11
20
|
Exclude:
|
@@ -18,3 +27,9 @@ Metrics/MethodLength:
|
|
18
27
|
Naming/FileName:
|
19
28
|
Exclude:
|
20
29
|
- lib/rubocop-ordered_methods.rb
|
30
|
+
|
31
|
+
# Use the semantic style. If a block has side effects use `do`, and if it is
|
32
|
+
# pure use `{}`. This style is too nuanced for a linter, so the cop is
|
33
|
+
# disabled.
|
34
|
+
Style/BlockDelimiters:
|
35
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [0.10] - 2021-03-10
|
10
|
+
|
11
|
+
### Removed
|
12
|
+
|
13
|
+
- Drop support for Ruby 2.4, 2.5, and 2.6
|
14
|
+
|
15
|
+
### Added
|
16
|
+
|
17
|
+
- Support for custom method qualifiers ([#11](https://github.com/shanecav84/rubocop-ordered_methods/pull/11)). Thanks @Darhazer.
|
18
|
+
- Setup CI ([#12](https://github.com/shanecav84/rubocop-ordered_methods/pull/12)). Thanks @Darhazer.
|
19
|
+
|
20
|
+
## [0.9] - 2021-03-10
|
21
|
+
|
22
|
+
### Added
|
23
|
+
|
24
|
+
- Autocorrection support for Sorbet signatures
|
25
|
+
|
9
26
|
## [0.8] - 2021-02-01
|
10
27
|
|
11
28
|
### Fixed
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -74,8 +74,23 @@ rubocop --require rubocop-ordered_methods
|
|
74
74
|
|
75
75
|
Name | Default value | Configurable values
|
76
76
|
--- | --- | ---
|
77
|
-
EnforcedStyle | `alphabetical` | `alphabetical`
|
78
|
-
IgnoredMethods | `initialize` | Array
|
77
|
+
EnforcedStyle | `'alphabetical'` | `'alphabetical'`
|
78
|
+
IgnoredMethods | `['initialize']` | Array
|
79
|
+
MethodQualifiers | `[]` | Array
|
80
|
+
Signature | `nil` | `'sorbet'`, `nil`
|
81
|
+
|
82
|
+
#### Example
|
83
|
+
|
84
|
+
```
|
85
|
+
# .rubocop.yml
|
86
|
+
Layout/OrderedMethods:
|
87
|
+
EnforcedStyle: alphabetical
|
88
|
+
IgnoredMethods:
|
89
|
+
- initialize
|
90
|
+
MethodQualifiers:
|
91
|
+
- memoize
|
92
|
+
Signature: sorbet
|
93
|
+
```
|
79
94
|
|
80
95
|
### Corrector
|
81
96
|
|
@@ -125,6 +140,23 @@ protected :instance_a
|
|
125
140
|
public :instance_a
|
126
141
|
```
|
127
142
|
|
143
|
+
#### Method qualifiers
|
144
|
+
Some gems (like `memery`, `memoist`, etc.) provide a DSL that modifies the method (e.g. for memoization).
|
145
|
+
Those DSL methods can be added to the `MethodQualifiers` configuration, and they will be respected.
|
146
|
+
|
147
|
+
E.g. the following source can be correctly ordered:
|
148
|
+
```ruby
|
149
|
+
def b; end;
|
150
|
+
memoize def a;end
|
151
|
+
```
|
152
|
+
|
153
|
+
#### Method signatures
|
154
|
+
|
155
|
+
Support for (Sorbet) method signatures was added to the corrector by
|
156
|
+
[#7](https://github.com/shanecav84/rubocop-ordered_methods/pull/7).
|
157
|
+
It is off by default due to performance concerns (not yet benchmarked). Enable
|
158
|
+
with `Signature: sorbet`.
|
159
|
+
|
128
160
|
#### Caveats
|
129
161
|
|
130
162
|
* The corrector will warn and refuse to order a method if it were to be
|
data/config/default.yml
CHANGED
@@ -10,9 +10,11 @@ module RuboCop
|
|
10
10
|
class OrderedMethodsCorrector
|
11
11
|
include QualifierNodeMatchers
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
# @param cop_config ::RuboCop::Config
|
14
|
+
def initialize(comment_locations, siblings, cop_config)
|
15
|
+
@comment_locations = comment_locations
|
15
16
|
@siblings = siblings
|
17
|
+
@cop_config = cop_config
|
16
18
|
end
|
17
19
|
|
18
20
|
def correct(node, previous_node)
|
@@ -45,13 +47,19 @@ module RuboCop
|
|
45
47
|
(qualifier?(next_sibling) || alias?(next_sibling)) == node.method_name
|
46
48
|
end
|
47
49
|
|
50
|
+
# @param node RuboCop::AST::DefNode
|
51
|
+
# @param source_range Parser::Source::Range
|
52
|
+
# @return Parser::Source::Range
|
48
53
|
def join_comments(node, source_range)
|
49
|
-
@
|
54
|
+
@comment_locations[node.loc].each do |comment|
|
50
55
|
source_range = source_range.join(comment.loc.expression)
|
51
56
|
end
|
52
57
|
source_range
|
53
58
|
end
|
54
59
|
|
60
|
+
# @param node RuboCop::AST::DefNode
|
61
|
+
# @param source_range Parser::Source::Range
|
62
|
+
# @return Parser::Source::Range
|
55
63
|
def join_modifiers_and_aliases(node, source_range)
|
56
64
|
preceding_qualifier_index = node.sibling_index
|
57
65
|
last_qualifier_index = find_last_qualifier_index(node)
|
@@ -64,12 +72,46 @@ module RuboCop
|
|
64
72
|
source_range
|
65
73
|
end
|
66
74
|
|
75
|
+
# @param node RuboCop::AST::DefNode
|
76
|
+
# @param source_range Parser::Source::Range
|
77
|
+
# @return Parser::Source::Range
|
78
|
+
def join_signature(node, source_range)
|
79
|
+
sib = node.left_sibling
|
80
|
+
if signature?(sib)
|
81
|
+
# If there is a comment directly above the sig, first calculate the
|
82
|
+
# range that covers both.
|
83
|
+
with_comment = join_comments(sib, sib.source_range)
|
84
|
+
source_range.join(with_comment)
|
85
|
+
else
|
86
|
+
source_range
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def join_signature?
|
91
|
+
@cop_config['Signature'] == 'sorbet'
|
92
|
+
end
|
93
|
+
|
94
|
+
# @param node RuboCop::AST::DefNode
|
95
|
+
# @return Parser::Source::Range
|
67
96
|
def join_surroundings(node)
|
68
97
|
with_modifiers_and_aliases = join_modifiers_and_aliases(
|
69
98
|
node,
|
70
99
|
node.source_range
|
71
100
|
)
|
72
|
-
join_comments(node, with_modifiers_and_aliases)
|
101
|
+
with_comments = join_comments(node, with_modifiers_and_aliases)
|
102
|
+
if join_signature?
|
103
|
+
join_signature(node, with_comments)
|
104
|
+
else
|
105
|
+
with_comments
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# https://sorbet.org/docs/sigs
|
110
|
+
# @param node RuboCop::AST::Node
|
111
|
+
def signature?(node)
|
112
|
+
return false unless node&.type == :block
|
113
|
+
child = node.children.first
|
114
|
+
child&.type == :send && child.method_name == :sig
|
73
115
|
end
|
74
116
|
end
|
75
117
|
end
|
@@ -35,20 +35,27 @@ module RuboCop
|
|
35
35
|
include RangeHelp
|
36
36
|
|
37
37
|
COMPARISONS = {
|
38
|
-
'alphabetical' => lambda do |
|
39
|
-
(
|
38
|
+
'alphabetical' => lambda do |left_node, right_node|
|
39
|
+
(method_name(left_node) <=> method_name(right_node)) != 1
|
40
40
|
end
|
41
41
|
}.freeze
|
42
42
|
ERR_INVALID_COMPARISON = 'Invalid "Comparison" config for ' \
|
43
43
|
"#{cop_name}. Expected one of: #{COMPARISONS.keys.join(', ')}".freeze
|
44
44
|
|
45
|
+
def self.method_name(node)
|
46
|
+
return node.method_name unless node.send_type?
|
47
|
+
|
48
|
+
node.first_argument.method_name
|
49
|
+
end
|
50
|
+
|
45
51
|
def autocorrect(node)
|
46
|
-
|
52
|
+
_siblings, corrector = cache(node)
|
53
|
+
corrector.correct(node, @previous_node)
|
47
54
|
end
|
48
55
|
|
49
56
|
def on_begin(node)
|
50
|
-
cache(node)
|
51
|
-
consecutive_methods(
|
57
|
+
siblings, _corrector = cache(node)
|
58
|
+
consecutive_methods(siblings) do |previous, current|
|
52
59
|
unless ordered?(previous, current)
|
53
60
|
@previous_node = previous
|
54
61
|
add_offense(
|
@@ -68,20 +75,33 @@ module RuboCop
|
|
68
75
|
(node.send_type? && node.bare_access_modifier?)
|
69
76
|
end
|
70
77
|
|
78
|
+
# rubocop:disable Metrics/MethodLength
|
71
79
|
# Cache to avoid traversing the AST multiple times
|
72
80
|
def cache(node)
|
73
|
-
@cache ||=
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
81
|
+
@cache ||= Hash.new do |h, key|
|
82
|
+
h[key.hash] = begin
|
83
|
+
siblings = node.children
|
84
|
+
|
85
|
+
# Init the corrector with the cache to avoid traversing the AST in
|
86
|
+
# the corrector.
|
87
|
+
#
|
88
|
+
# We always init the @corrector, even if @options[:auto_correct] is
|
89
|
+
# nil, because `add_offense` always attempts correction. This
|
90
|
+
# correction attempt is how RuboCop knows if the offense can be
|
91
|
+
# labeled "[Correctable]".
|
92
|
+
comment_locations = ::Parser::Source::Comment.associate_locations(
|
93
|
+
processed_source.ast,
|
94
|
+
processed_source.comments
|
95
|
+
)
|
96
|
+
corrector = OrderedMethodsCorrector.new(comment_locations, siblings, cop_config)
|
97
|
+
|
98
|
+
[siblings, corrector]
|
99
|
+
end
|
83
100
|
end
|
101
|
+
|
102
|
+
@cache[node.hash]
|
84
103
|
end
|
104
|
+
# rubocop:enable Metrics/MethodLength
|
85
105
|
|
86
106
|
# We disable `Style/ExplicitBlockArgument` for performance. See
|
87
107
|
# https://github.com/shanecav84/rubocop-ordered_methods/pull/5#pullrequestreview-562957146
|
@@ -99,10 +119,7 @@ module RuboCop
|
|
99
119
|
|
100
120
|
def filter_relevant_nodes(nodes)
|
101
121
|
nodes.select do |node|
|
102
|
-
(
|
103
|
-
(node.defs_type? || node.def_type?) &&
|
104
|
-
!ignored_method?(node.method_name)
|
105
|
-
) || (node.send_type? && node.bare_access_modifier?)
|
122
|
+
relevant_node?(node) || (node.send_type? && qualifier_macro?(node))
|
106
123
|
end
|
107
124
|
end
|
108
125
|
|
@@ -134,6 +151,17 @@ module RuboCop
|
|
134
151
|
|
135
152
|
comparison.call(left_method, right_method)
|
136
153
|
end
|
154
|
+
|
155
|
+
def qualifier_macro?(node)
|
156
|
+
return true if node.bare_access_modifier?
|
157
|
+
|
158
|
+
cop_config['MethodQualifiers'].to_a.include?(node.method_name.to_s) &&
|
159
|
+
relevant_node?(node.first_argument)
|
160
|
+
end
|
161
|
+
|
162
|
+
def relevant_node?(node)
|
163
|
+
(node.defs_type? || node.def_type?) && !ignored_method?(node.method_name)
|
164
|
+
end
|
137
165
|
end
|
138
166
|
end
|
139
167
|
end
|
@@ -20,9 +20,16 @@ module RuboCop
|
|
20
20
|
def_node_matcher :alias_method?,
|
21
21
|
'(send nil? {:alias_method} ... (sym $_method_name))'
|
22
22
|
def_node_matcher :qualifier?, <<-PATTERN
|
23
|
-
(send nil?
|
24
|
-
... (sym $_method_name))
|
23
|
+
(send nil? #method_qualifier? ... (sym $_method_name))
|
25
24
|
PATTERN
|
25
|
+
|
26
|
+
def method_qualifier?(name)
|
27
|
+
qualifiers.include?(name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def qualifiers
|
31
|
+
@qualifiers ||= QUALIFIERS + @cop_config['MethodQualifiers'].to_a.map(&:to_sym)
|
32
|
+
end
|
26
33
|
end
|
27
34
|
end
|
28
35
|
end
|
@@ -5,14 +5,14 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'rubocop-ordered_methods'
|
8
|
-
spec.version = '0.
|
8
|
+
spec.version = '0.10'
|
9
9
|
spec.authors = ['Shane Cavanaugh']
|
10
10
|
spec.email = ['shane@shanecav.net']
|
11
11
|
|
12
12
|
spec.summary = 'Checks that methods are ordered alphabetically.'
|
13
13
|
spec.homepage = 'https://github.com/shanecav84/rubocop-ordered_methods'
|
14
14
|
spec.license = 'MIT'
|
15
|
-
spec.required_ruby_version = '>= 2.
|
15
|
+
spec.required_ruby_version = '>= 2.7'
|
16
16
|
|
17
17
|
# Specify which files should be added to the gem when it is released.
|
18
18
|
# The `git ls-files -z` loads the files in the RubyGem that have been added
|
@@ -28,7 +28,5 @@ Gem::Specification.new do |spec|
|
|
28
28
|
|
29
29
|
spec.add_runtime_dependency 'rubocop', '>= 1.0'
|
30
30
|
|
31
|
-
spec.
|
32
|
-
spec.add_development_dependency 'rake', '~> 12.3.3'
|
33
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
31
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
34
32
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-ordered_methods
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.10'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shane Cavanaugh
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -24,48 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: bundler
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rake
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 12.3.3
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 12.3.3
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rspec
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '3.0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '3.0'
|
69
27
|
description:
|
70
28
|
email:
|
71
29
|
- shane@shanecav.net
|
@@ -73,6 +31,7 @@ executables: []
|
|
73
31
|
extensions: []
|
74
32
|
extra_rdoc_files: []
|
75
33
|
files:
|
34
|
+
- ".github/workflows/main.yml"
|
76
35
|
- ".gitignore"
|
77
36
|
- ".rakeTasks"
|
78
37
|
- ".rubocop.yml"
|
@@ -96,7 +55,8 @@ files:
|
|
96
55
|
homepage: https://github.com/shanecav84/rubocop-ordered_methods
|
97
56
|
licenses:
|
98
57
|
- MIT
|
99
|
-
metadata:
|
58
|
+
metadata:
|
59
|
+
rubygems_mfa_required: 'true'
|
100
60
|
post_install_message:
|
101
61
|
rdoc_options: []
|
102
62
|
require_paths:
|
@@ -105,14 +65,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
65
|
requirements:
|
106
66
|
- - ">="
|
107
67
|
- !ruby/object:Gem::Version
|
108
|
-
version: '2.
|
68
|
+
version: '2.7'
|
109
69
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
70
|
requirements:
|
111
71
|
- - ">="
|
112
72
|
- !ruby/object:Gem::Version
|
113
73
|
version: '0'
|
114
74
|
requirements: []
|
115
|
-
rubygems_version: 3.
|
75
|
+
rubygems_version: 3.2.33
|
116
76
|
signing_key:
|
117
77
|
specification_version: 4
|
118
78
|
summary: Checks that methods are ordered alphabetically.
|