rubocop-ordered_methods 0.2 → 0.7
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/.gitignore +1 -0
- data/.rakeTasks +7 -0
- data/.rubocop.yml +5 -0
- data/.rubocop_todo.yml +12 -9
- data/.travis.yml +3 -2
- data/CHANGELOG.md +65 -0
- data/Gemfile +2 -3
- data/README.md +86 -23
- data/Rakefile +2 -0
- data/bin/console +1 -0
- data/config/default.yml +6 -0
- data/lib/rubocop-ordered_methods.rb +5 -0
- data/lib/rubocop/cop/alias_method_order_verifier.rb +67 -0
- data/lib/rubocop/cop/correctors/ordered_methods_corrector.rb +48 -101
- data/lib/rubocop/cop/layout/ordered_methods.rb +59 -53
- data/lib/rubocop/cop/qualifier_node_matchers.rb +28 -0
- data/lib/rubocop/ordered_methods.rb +18 -0
- data/rubocop-ordered_methods.gemspec +16 -13
- metadata +24 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c161660f9f4755d2e7fe826d18a1cd704d9f62071736ea5dc4f8e540ed78cd14
|
|
4
|
+
data.tar.gz: 6f464af4d215c37dbeb402e0d81a730dcd96f6a77ae40892d60a382a847002c8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: af7672dbef3e4fc3d5b84a814ec08f6e372d0dadc8d1fced783c7b74a6a4abc43c9d33e53b97b2c9b4e75bba73106b9a5238daaa9709333c6a477496eb18dfa3
|
|
7
|
+
data.tar.gz: 73c5f91133bd0a8c1e8acd669d1c8df7e969670250a49df9698e0ea547c20ba92e0282032007fdd1406948a700c16b996c832f63269ef2014736a7165cc177d6
|
data/.gitignore
CHANGED
data/.rakeTasks
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<Settings><!--This file was automatically generated by Ruby plugin.
|
|
3
|
+
You are allowed to:
|
|
4
|
+
1. Remove rake task
|
|
5
|
+
2. Add existing rake tasks
|
|
6
|
+
To add existing rake tasks automatically delete this file and reload the project.
|
|
7
|
+
--><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build rubocop-ordered_methods-0.5.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Remove any temporary products" fullCmd="clean" taksId="clean" /><RakeTask description="Remove any generated files" fullCmd="clobber" taksId="clobber" /><RakeTask description="Build and install rubocop-ordered_methods-0.5.gem into system gems" fullCmd="install" taksId="install" /><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="Build and install rubocop-ordered_methods-0.5.gem into system gems without network access" fullCmd="install:local" taksId="local" /></RakeGroup><RakeTask description="Create tag v0.5 and build and push rubocop-ordered_methods-0.5.gem to rubygems.org" fullCmd="release[remote]" taksId="release[remote]" /><RakeTask description="Run RuboCop" fullCmd="rubocop" taksId="rubocop" /><RakeGroup description="" fullCmd="" taksId="rubocop"><RakeTask description="Auto-correct RuboCop offenses" fullCmd="rubocop:auto_correct" taksId="auto_correct" /></RakeGroup><RakeTask description="Run RSpec code examples" fullCmd="spec" taksId="spec" /><RakeTask description="" fullCmd="default" taksId="default" /><RakeTask description="" fullCmd="release" taksId="release" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup></RakeGroup></Settings>
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on
|
|
3
|
+
# on 2021-01-05 20:47:55 UTC using RuboCop version 1.7.0.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
8
8
|
|
|
9
9
|
# Offense count: 1
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
|
|
11
|
+
Metrics/MethodLength:
|
|
12
|
+
Max: 11
|
|
12
13
|
|
|
13
14
|
# Offense count: 1
|
|
14
|
-
#
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
# Cop supports --auto-correct.
|
|
16
|
+
Style/IfUnlessModifier:
|
|
17
|
+
Exclude:
|
|
18
|
+
- 'lib/rubocop/cop/layout/ordered_methods.rb'
|
|
17
19
|
|
|
18
20
|
# Offense count: 1
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
# Cop supports --auto-correct.
|
|
22
|
+
Style/RedundantFreeze:
|
|
23
|
+
Exclude:
|
|
24
|
+
- 'lib/rubocop/cop/layout/ordered_methods.rb'
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
All notable changes to this project will be documented in this file.
|
|
3
|
+
|
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
- nothing
|
|
10
|
+
|
|
11
|
+
## [0.7] - 2021-01-11
|
|
12
|
+
|
|
13
|
+
### Removed
|
|
14
|
+
|
|
15
|
+
- Drop Ruby 2.3 support
|
|
16
|
+
- Drop support for rubocop < 1.0
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Support for rubocop >= 1.0 ([#5](https://github.com/shanecav84/rubocop-ordered_methods/pull/5)). Thanks @jaredbeck.
|
|
21
|
+
|
|
22
|
+
## [0.6] - 2020-03-01
|
|
23
|
+
|
|
24
|
+
### Security
|
|
25
|
+
|
|
26
|
+
- Upgrade rake to avoid vulnerability https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-8130
|
|
27
|
+
- rake is a development dependency for this gem, so shouldn't have been a risk for production
|
|
28
|
+
|
|
29
|
+
## [0.5] - 2019-11-05
|
|
30
|
+
|
|
31
|
+
### Removed
|
|
32
|
+
|
|
33
|
+
- Drop Ruby 2.2 support
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Nonadjacent qualifiers are now autocorrected (#4). Thanks @adamkiczula.
|
|
38
|
+
- Cache AST traversals for significant speed up on large files
|
|
39
|
+
|
|
40
|
+
## [0.4] - 2019-06-11
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
- More robust autocorrection of a method and its surroundings (see `Corrector` in the `README`).
|
|
45
|
+
|
|
46
|
+
## [0.3] - 2019-02-17
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- Configuration defaults
|
|
51
|
+
|
|
52
|
+
## [0.2] - 2019-02-17
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
|
|
56
|
+
- Autocorrector
|
|
57
|
+
|
|
58
|
+
## [0.1] - 2019-02-17
|
|
59
|
+
|
|
60
|
+
Initial release.
|
|
61
|
+
|
|
62
|
+
[Unreleased]: https://github.com/shanecav84/rubocop-ordered_methods/compare/v0.3...HEAD
|
|
63
|
+
[0.3]: https://github.com/shanecav84/rubocop-ordered_methods/compare/v0.2...v0.3
|
|
64
|
+
[0.2]: https://github.com/shanecav84/rubocop-ordered_methods/compare/v0.1...v0.2
|
|
65
|
+
[0.1]: https://github.com/shanecav84/rubocop-ordered_methods/releases/tag/v0.1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
1
|
+
[](https://badge.fury.io/rb/rubocop-ordered_methods)
|
|
2
|
+
[](https://travis-ci.org/shanecav84/rubocop-ordered_methods)
|
|
3
|
+
|
|
1
4
|
# RuboCop OrderedMethods
|
|
2
5
|
|
|
3
|
-
Check that methods are defined alphabetically
|
|
4
|
-
|
|
6
|
+
Check that methods are defined alphabetically per access modifier block (class,
|
|
7
|
+
public, private, protected). Includes [autocorrection](#corrector).
|
|
5
8
|
|
|
6
9
|
```ruby
|
|
7
10
|
# bad
|
|
8
|
-
def self.
|
|
9
|
-
def self.
|
|
11
|
+
def self.b_class; end
|
|
12
|
+
def self.a_class; end
|
|
10
13
|
|
|
11
|
-
def
|
|
12
|
-
def
|
|
14
|
+
def b_public; end
|
|
15
|
+
def a_public; end
|
|
13
16
|
|
|
14
17
|
private
|
|
15
18
|
|
|
16
|
-
def
|
|
17
|
-
def
|
|
19
|
+
def b_private; end
|
|
20
|
+
def a_private; end
|
|
18
21
|
|
|
19
22
|
# good
|
|
20
|
-
def self.
|
|
21
|
-
def self.
|
|
23
|
+
def self.a_class; end
|
|
24
|
+
def self.b_class; end
|
|
22
25
|
|
|
23
|
-
def
|
|
24
|
-
def
|
|
26
|
+
def a_public; end
|
|
27
|
+
def b_public; end
|
|
25
28
|
|
|
26
29
|
private
|
|
27
30
|
|
|
28
|
-
def
|
|
29
|
-
def
|
|
31
|
+
def a_private; end
|
|
32
|
+
def b_private; end
|
|
30
33
|
```
|
|
31
34
|
|
|
32
35
|
## Installation
|
|
@@ -47,7 +50,7 @@ Or install it yourself as:
|
|
|
47
50
|
|
|
48
51
|
## Usage
|
|
49
52
|
|
|
50
|
-
You need to tell RuboCop to load the OrderedMethods extension. There are
|
|
53
|
+
You need to tell RuboCop to load the OrderedMethods extension. There are two
|
|
51
54
|
ways to do this:
|
|
52
55
|
|
|
53
56
|
### RuboCop configuration file
|
|
@@ -71,17 +74,70 @@ rubocop --require rubocop-ordered_methods
|
|
|
71
74
|
|
|
72
75
|
Name | Default value | Configurable values
|
|
73
76
|
--- | --- | ---
|
|
77
|
+
EnforcedStyle | `alphabetical` | `alphabetical`
|
|
74
78
|
IgnoredMethods | `initialize` | Array
|
|
75
79
|
|
|
76
80
|
### Corrector
|
|
77
81
|
|
|
78
|
-
The corrector will attempt to order methods
|
|
79
|
-
include surrounding comments and the qualifiers listed in
|
|
80
|
-
`::RuboCop::Cop::
|
|
82
|
+
The corrector will attempt to order methods based on the `EnforcedStyle`. It attempts to
|
|
83
|
+
include surrounding comments and the qualifiers (e.g., aliases) listed in
|
|
84
|
+
`::RuboCop::Cop::OrderedMethodsCorrector::QUALIFIERS`. The following (monstrous)
|
|
85
|
+
source is able to be correctly ordered:
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
# Long
|
|
89
|
+
# Preceding
|
|
90
|
+
# Comment
|
|
91
|
+
# class_b
|
|
92
|
+
def self.class_b; end
|
|
93
|
+
private_class_method :class_b
|
|
94
|
+
|
|
95
|
+
def self.class_a; end
|
|
96
|
+
# Long
|
|
97
|
+
# Succeeding
|
|
98
|
+
# Comment
|
|
99
|
+
# class_a
|
|
100
|
+
public_class_method :class_a
|
|
101
|
+
|
|
102
|
+
# Preceding comment for instance_b
|
|
103
|
+
def instance_b; end
|
|
104
|
+
# Long
|
|
105
|
+
# Succeeding
|
|
106
|
+
# Comment
|
|
107
|
+
# instance_b
|
|
108
|
+
alias_method :orig_instance_b, :instance_b
|
|
109
|
+
module_function :instance_b
|
|
110
|
+
private :instance_b
|
|
111
|
+
protected :instance_b
|
|
112
|
+
public :instance_b
|
|
113
|
+
|
|
114
|
+
# Long
|
|
115
|
+
# Preceding
|
|
116
|
+
# Comment
|
|
117
|
+
# instance_a
|
|
118
|
+
def instance_a; end
|
|
119
|
+
# Succeeding comment for instance_a
|
|
120
|
+
alias :new_instance_a :instance_a
|
|
121
|
+
alias_method :orig_instance_a, :instance_a
|
|
122
|
+
module_function :instance_a
|
|
123
|
+
private :instance_a
|
|
124
|
+
protected :instance_a
|
|
125
|
+
public :instance_a
|
|
126
|
+
```
|
|
81
127
|
|
|
82
128
|
#### Caveats
|
|
83
|
-
|
|
84
|
-
|
|
129
|
+
|
|
130
|
+
* The corrector will warn and refuse to order a method if it were to be
|
|
131
|
+
defined before its alias
|
|
132
|
+
* If there's ambiguity about which method a comment or qualifier belongs to,
|
|
133
|
+
the corrector might fail to order correctly. For example, in the following,
|
|
134
|
+
the corrector would incorrectly order the comment as a comment of `a`:
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
def b; end
|
|
138
|
+
# Comment b
|
|
139
|
+
def a; end
|
|
140
|
+
```
|
|
85
141
|
|
|
86
142
|
## Development
|
|
87
143
|
|
|
@@ -94,12 +150,19 @@ bundle exec rake
|
|
|
94
150
|
|
|
95
151
|
## Contributing
|
|
96
152
|
|
|
97
|
-
Bug reports and pull requests are welcome on GitHub at
|
|
153
|
+
Bug reports and pull requests are welcome on GitHub at
|
|
154
|
+
https://github.com/shanecav84/rubocop-ordered_methods. This project is intended
|
|
155
|
+
to be a safe, welcoming space for collaboration, and contributors are expected
|
|
156
|
+
to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of
|
|
157
|
+
conduct.
|
|
98
158
|
|
|
99
159
|
## License
|
|
100
160
|
|
|
101
|
-
The gem is available as open source under the terms of the
|
|
161
|
+
The gem is available as open source under the terms of the
|
|
162
|
+
[MIT License](https://opensource.org/licenses/MIT).
|
|
102
163
|
|
|
103
164
|
## Code of Conduct
|
|
104
165
|
|
|
105
|
-
Everyone interacting in the RuboCop OrderedMethods project’s codebases, issue
|
|
166
|
+
Everyone interacting in the RuboCop OrderedMethods project’s codebases, issue
|
|
167
|
+
trackers, chat rooms and mailing lists is expected to follow the
|
|
168
|
+
[code of conduct](https://github.com/shanecav84/rubocop-ordered_methods/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
data/config/default.yml
ADDED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rubocop'
|
|
4
|
+
require_relative 'rubocop/ordered_methods'
|
|
2
5
|
require_relative 'rubocop/cop/layout/ordered_methods'
|
|
3
6
|
require_relative 'rubocop/cop/correctors/ordered_methods_corrector'
|
|
7
|
+
|
|
8
|
+
RuboCop::OrderedMethods.inject_defaults!
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'qualifier_node_matchers'
|
|
4
|
+
|
|
5
|
+
module RuboCop
|
|
6
|
+
module Cop
|
|
7
|
+
# This verifies a method is defined before its alias
|
|
8
|
+
class AliasMethodOrderVerifier
|
|
9
|
+
class << self
|
|
10
|
+
include IgnoredNode
|
|
11
|
+
include QualifierNodeMatchers
|
|
12
|
+
|
|
13
|
+
# Disable cop for freezing on Ruby 2.2
|
|
14
|
+
# rubocop:disable Style/RedundantFreeze
|
|
15
|
+
ALIAS_BEFORE_METHOD_WARNING_FMT = "Won't reorder " \
|
|
16
|
+
'%<first_method_name>s and %<second_method_name>s because ' \
|
|
17
|
+
'alias for %<first_method_name>s would be declared before ' \
|
|
18
|
+
'its method definition.'.freeze
|
|
19
|
+
# rubocop:enable Style/RedundantFreeze
|
|
20
|
+
|
|
21
|
+
# rubocop:disable Style/GuardClause
|
|
22
|
+
def verify!(current_node, previous_node)
|
|
23
|
+
if moving_after_alias?(current_node, previous_node)
|
|
24
|
+
ignore_node(current_node)
|
|
25
|
+
raise_warning!(current_node.method_name, previous_node.method_name)
|
|
26
|
+
end
|
|
27
|
+
if moving_after_alias?(previous_node, current_node)
|
|
28
|
+
ignore_node(previous_node)
|
|
29
|
+
raise_warning!(previous_node.method_name, current_node.method_name)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
# rubocop:enable Style/GuardClause
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def find_aliases(current_node, siblings)
|
|
37
|
+
siblings.select do |sibling|
|
|
38
|
+
(alias?(sibling) || alias_method?(sibling)) ==
|
|
39
|
+
current_node.method_name
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# We don't want a method to be defined after its alias
|
|
44
|
+
def moving_after_alias?(current_node, previous_node)
|
|
45
|
+
siblings = current_node.parent.children
|
|
46
|
+
current_node_aliases = find_aliases(current_node, siblings)
|
|
47
|
+
filter = current_node_aliases.delete_if do |cna|
|
|
48
|
+
cna.sibling_index > current_node.sibling_index
|
|
49
|
+
end
|
|
50
|
+
return false if filter.empty?
|
|
51
|
+
|
|
52
|
+
current_node_aliases.any? do |cna|
|
|
53
|
+
previous_node.sibling_index > cna.sibling_index
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def raise_warning!(first_method_name, second_method_name)
|
|
58
|
+
raise Warning, format(
|
|
59
|
+
ALIAS_BEFORE_METHOD_WARNING_FMT,
|
|
60
|
+
first_method_name: first_method_name,
|
|
61
|
+
second_method_name: second_method_name
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -1,128 +1,75 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative '../layout/ordered_methods'
|
|
4
|
+
require_relative '../alias_method_order_verifier'
|
|
5
|
+
require_relative '../qualifier_node_matchers'
|
|
4
6
|
|
|
5
7
|
module RuboCop
|
|
6
8
|
module Cop
|
|
7
9
|
# This auto-corrects method order
|
|
8
10
|
class OrderedMethodsCorrector
|
|
9
|
-
|
|
10
|
-
include IgnoredNode
|
|
11
|
-
extend NodePattern::Macros
|
|
11
|
+
include QualifierNodeMatchers
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
QUALIFIERS = (
|
|
18
|
-
%i[alias_method private_class_method public_class_method] +
|
|
19
|
-
::RuboCop::Cop::Layout::OrderedMethods::
|
|
20
|
-
VISIBILITY_MODIFIERS
|
|
21
|
-
).freeze
|
|
22
|
-
|
|
23
|
-
def_node_matcher :alias?, '(:alias ... (sym $_method_name))'
|
|
24
|
-
def_node_matcher :qualifier?, <<-PATTERN
|
|
25
|
-
(send nil? {#{QUALIFIERS.map(&:inspect).join(' ')}}
|
|
26
|
-
... (sym $_method_name))
|
|
27
|
-
PATTERN
|
|
28
|
-
|
|
29
|
-
def correct(processed_source, node, previous_node)
|
|
30
|
-
@processed_source = processed_source
|
|
31
|
-
@current_node = node
|
|
32
|
-
@previous_node = previous_node
|
|
13
|
+
def initialize(comments, siblings)
|
|
14
|
+
@comments = comments
|
|
15
|
+
@siblings = siblings
|
|
16
|
+
end
|
|
33
17
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
18
|
+
def correct(node, previous_node)
|
|
19
|
+
AliasMethodOrderVerifier.verify!(node, previous_node)
|
|
20
|
+
current_range = join_surroundings(node)
|
|
21
|
+
previous_range = join_surroundings(previous_node)
|
|
22
|
+
lambda do |corrector|
|
|
23
|
+
corrector.replace(current_range, previous_range.source)
|
|
24
|
+
corrector.replace(previous_range, current_range.source)
|
|
41
25
|
end
|
|
26
|
+
end
|
|
42
27
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def found_qualifier?(node, next_sibling)
|
|
46
|
-
(qualifier?(next_sibling) || alias?(next_sibling)) == node.method_name
|
|
47
|
-
end
|
|
28
|
+
private
|
|
48
29
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
end
|
|
55
|
-
filter = current_node_aliases.delete_if do |cna|
|
|
56
|
-
cna.sibling_index == current_node.sibling_index + 1
|
|
57
|
-
end
|
|
58
|
-
return false if filter.empty?
|
|
30
|
+
def find_last_qualifier_index(node)
|
|
31
|
+
preceding_qualifier_index = node.sibling_index
|
|
32
|
+
last_qualifier_index = @siblings.length - 1
|
|
33
|
+
while preceding_qualifier_index < last_qualifier_index
|
|
34
|
+
break if found_qualifier?(node, @siblings[last_qualifier_index])
|
|
59
35
|
|
|
60
|
-
|
|
61
|
-
previous_node.sibling_index > cna.sibling_index
|
|
62
|
-
end
|
|
36
|
+
last_qualifier_index -= 1
|
|
63
37
|
end
|
|
64
38
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if moving_after_alias?(@current_node, @previous_node)
|
|
68
|
-
ignore_node(@current_node)
|
|
69
|
-
raise Warning, format(
|
|
70
|
-
ALIAS_BEFORE_METHOD_WARNING_FMT,
|
|
71
|
-
first_method_name: @current_node.method_name,
|
|
72
|
-
second_method_name: @previous_node.method_name
|
|
73
|
-
)
|
|
74
|
-
end
|
|
75
|
-
if moving_after_alias?(@previous_node, @current_node)
|
|
76
|
-
ignore_node(@previous_node)
|
|
77
|
-
raise Warning, format(
|
|
78
|
-
ALIAS_BEFORE_METHOD_WARNING_FMT,
|
|
79
|
-
first_method_name: @previous_node.method_name,
|
|
80
|
-
second_method_name: @current_node.method_name
|
|
81
|
-
)
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
# rubocop:enable Metrics/MethodLength, Style/GuardClause
|
|
39
|
+
last_qualifier_index
|
|
40
|
+
end
|
|
85
41
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
.join(with_preceding_comments(node))
|
|
89
|
-
.join(with_succeeding_comments(node))
|
|
90
|
-
end
|
|
42
|
+
def found_qualifier?(node, next_sibling)
|
|
43
|
+
return false if next_sibling.nil?
|
|
91
44
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
siblings = node.parent.children
|
|
95
|
-
qualifier_index = node.sibling_index
|
|
96
|
-
while found_qualifier?(node, siblings[qualifier_index + 1])
|
|
97
|
-
qualifier_index += 1
|
|
98
|
-
end
|
|
99
|
-
found_node_range = with_comments(siblings[qualifier_index])
|
|
100
|
-
surrounding_range.join(found_node_range)
|
|
101
|
-
end
|
|
45
|
+
(qualifier?(next_sibling) || alias?(next_sibling)) == node.method_name
|
|
46
|
+
end
|
|
102
47
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
surrounding_range = surrounding_range.join(comment.loc.expression)
|
|
107
|
-
end
|
|
108
|
-
surrounding_range
|
|
48
|
+
def join_comments(node, source_range)
|
|
49
|
+
@comments[node].each do |comment|
|
|
50
|
+
source_range = source_range.join(comment.loc.expression)
|
|
109
51
|
end
|
|
52
|
+
source_range
|
|
53
|
+
end
|
|
110
54
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
55
|
+
def join_modifiers_and_aliases(node, source_range)
|
|
56
|
+
preceding_qualifier_index = node.sibling_index
|
|
57
|
+
last_qualifier_index = find_last_qualifier_index(node)
|
|
58
|
+
while preceding_qualifier_index < last_qualifier_index
|
|
59
|
+
source_range = source_range.join(
|
|
60
|
+
@siblings[preceding_qualifier_index + 1].source_range
|
|
61
|
+
)
|
|
62
|
+
preceding_qualifier_index += 1
|
|
119
63
|
end
|
|
64
|
+
source_range
|
|
65
|
+
end
|
|
120
66
|
|
|
121
|
-
|
|
67
|
+
def join_surroundings(node)
|
|
68
|
+
with_modifiers_and_aliases = join_modifiers_and_aliases(
|
|
69
|
+
node,
|
|
122
70
|
node.source_range
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
end
|
|
71
|
+
)
|
|
72
|
+
join_comments(node, with_modifiers_and_aliases)
|
|
126
73
|
end
|
|
127
74
|
end
|
|
128
75
|
end
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
module RuboCop
|
|
4
4
|
module Cop
|
|
5
5
|
module Layout
|
|
6
|
-
#
|
|
6
|
+
# @example EnforcedStyle: alphabetical (default)
|
|
7
|
+
# # Check that methods are defined alphabetically.
|
|
7
8
|
#
|
|
8
|
-
# @example
|
|
9
9
|
# # bad
|
|
10
10
|
# def self.b; end
|
|
11
11
|
# def self.a; end
|
|
@@ -33,98 +33,104 @@ module RuboCop
|
|
|
33
33
|
include IgnoredMethods
|
|
34
34
|
include RangeHelp
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def_node_matcher :class_def?, 'defs'
|
|
45
|
-
def_node_matcher :instance_def?, 'def'
|
|
46
|
-
def_node_matcher :visibility_modifier?, <<-PATTERN
|
|
47
|
-
(send nil? { #{VISIBILITY_MODIFIERS.map(&:inspect).join(' ')} })
|
|
48
|
-
PATTERN
|
|
36
|
+
COMPARISONS = {
|
|
37
|
+
'alphabetical' => lambda do |left_method, right_method|
|
|
38
|
+
(left_method.method_name <=> right_method.method_name) != 1
|
|
39
|
+
end
|
|
40
|
+
}.freeze
|
|
41
|
+
ERR_INVALID_COMPARISON = 'Invalid "Comparison" config for ' \
|
|
42
|
+
"#{cop_name}. Expected one of: #{COMPARISONS.keys.join(', ')}".freeze
|
|
49
43
|
|
|
50
44
|
def autocorrect(node)
|
|
51
|
-
|
|
52
|
-
processed_source,
|
|
53
|
-
node,
|
|
54
|
-
@previous_node
|
|
55
|
-
)
|
|
45
|
+
@corrector.correct(node, @previous_node)
|
|
56
46
|
end
|
|
57
47
|
|
|
58
48
|
def on_begin(node)
|
|
59
|
-
|
|
49
|
+
cache(node)
|
|
50
|
+
consecutive_methods(@siblings) do |previous, current|
|
|
60
51
|
unless ordered?(previous, current)
|
|
61
52
|
@previous_node = previous
|
|
62
|
-
add_offense(
|
|
53
|
+
add_offense(
|
|
54
|
+
current,
|
|
55
|
+
message: 'Methods should be sorted in ' \
|
|
56
|
+
"#{cop_config['EnforcedStyle']} order."
|
|
57
|
+
)
|
|
63
58
|
end
|
|
64
59
|
end
|
|
65
60
|
end
|
|
66
61
|
|
|
67
62
|
private
|
|
68
63
|
|
|
69
|
-
def
|
|
70
|
-
|
|
64
|
+
def access_modified?(node, is_class_method_block)
|
|
65
|
+
(node.defs_type? && !is_class_method_block) ||
|
|
66
|
+
(node.def_type? && is_class_method_block) ||
|
|
67
|
+
(node.send_type? && node.bare_access_modifier?)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Cache to avoid traversing the AST multiple times
|
|
71
|
+
def cache(node)
|
|
72
|
+
@cache ||= begin
|
|
73
|
+
@siblings = node.children
|
|
74
|
+
|
|
75
|
+
# Init the corrector with the cache to avoid traversing
|
|
76
|
+
# the AST in the corrector
|
|
77
|
+
if @options[:auto_correct]
|
|
78
|
+
comments = processed_source.ast_with_comments
|
|
79
|
+
@corrector = OrderedMethodsCorrector.new(comments, @siblings)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# We disable `Style/ExplicitBlockArgument` for performance. See
|
|
85
|
+
# https://github.com/shanecav84/rubocop-ordered_methods/pull/5#pullrequestreview-562957146
|
|
86
|
+
# rubocop:disable Style/ExplicitBlockArgument
|
|
87
|
+
def consecutive_methods(nodes)
|
|
88
|
+
filtered = filter_relevant_nodes(nodes)
|
|
89
|
+
filtered_and_grouped = group_methods_by_access_modifier(filtered)
|
|
90
|
+
filtered_and_grouped.each do |method_group|
|
|
71
91
|
method_group.each_cons(2) do |left_method, right_method|
|
|
72
92
|
yield left_method, right_method
|
|
73
93
|
end
|
|
74
94
|
end
|
|
75
95
|
end
|
|
96
|
+
# rubocop:enable Style/ExplicitBlockArgument
|
|
76
97
|
|
|
77
98
|
def filter_relevant_nodes(nodes)
|
|
78
99
|
nodes.select do |node|
|
|
79
100
|
(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
) && !ignored_method?(node.method_name)
|
|
101
|
+
(node.defs_type? || node.def_type?) &&
|
|
102
|
+
!ignored_method?(node.method_name)
|
|
103
|
+
) || (node.send_type? && node.bare_access_modifier?)
|
|
84
104
|
end
|
|
85
105
|
end
|
|
86
106
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# Group methods by the visiblity block they are declared in. Multiple
|
|
92
|
-
# blocks of the same visiblity will have their methods grouped
|
|
107
|
+
# Group methods by the access modifier block they are declared in.
|
|
108
|
+
# Multiple blocks of the same modifier will have their methods grouped
|
|
93
109
|
# separately; for example, the following would be separated into two
|
|
94
110
|
# groups:
|
|
95
111
|
# private
|
|
96
112
|
# def a; end
|
|
97
113
|
# private
|
|
98
114
|
# def b; end
|
|
99
|
-
|
|
100
|
-
def group_methods_by_visiblity_block(nodes)
|
|
115
|
+
def group_methods_by_access_modifier(nodes)
|
|
101
116
|
is_class_method_block = false
|
|
117
|
+
|
|
102
118
|
nodes.each_with_object([[]]) do |node, grouped_methods|
|
|
103
|
-
if
|
|
119
|
+
if access_modified?(node, is_class_method_block)
|
|
104
120
|
grouped_methods << []
|
|
105
121
|
end
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
is_class_method_block = false if instance_def?(node)
|
|
109
|
-
|
|
110
|
-
if visibility_modifier?(node)
|
|
111
|
-
is_class_method_block = false
|
|
112
|
-
next
|
|
113
|
-
end
|
|
122
|
+
is_class_method_block = node.defs_type?
|
|
123
|
+
next if node.send_type? && node.bare_access_modifier?
|
|
114
124
|
|
|
115
125
|
grouped_methods.last << node
|
|
116
126
|
end
|
|
117
127
|
end
|
|
118
|
-
# rubocop:enable Metrics/MethodLength
|
|
119
|
-
|
|
120
|
-
def new_visiblity_block?(node, is_class_method_block)
|
|
121
|
-
(class_def?(node) && !is_class_method_block) ||
|
|
122
|
-
(instance_def?(node) && is_class_method_block) ||
|
|
123
|
-
visibility_modifier?(node)
|
|
124
|
-
end
|
|
125
128
|
|
|
126
129
|
def ordered?(left_method, right_method)
|
|
127
|
-
|
|
130
|
+
comparison = COMPARISONS[cop_config['EnforcedStyle']]
|
|
131
|
+
raise Error, ERR_INVALID_COMPARISON if comparison.nil?
|
|
132
|
+
|
|
133
|
+
comparison.call(left_method, right_method)
|
|
128
134
|
end
|
|
129
135
|
end
|
|
130
136
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
# defines matchers for qualifier nodes
|
|
6
|
+
module QualifierNodeMatchers
|
|
7
|
+
extend NodePattern::Macros
|
|
8
|
+
|
|
9
|
+
QUALIFIERS = %i[
|
|
10
|
+
alias_method
|
|
11
|
+
module_function
|
|
12
|
+
private_class_method
|
|
13
|
+
public_class_method
|
|
14
|
+
private
|
|
15
|
+
protected
|
|
16
|
+
public
|
|
17
|
+
].freeze
|
|
18
|
+
|
|
19
|
+
def_node_matcher :alias?, '(:alias ... (sym $_method_name))'
|
|
20
|
+
def_node_matcher :alias_method?,
|
|
21
|
+
'(send nil? {:alias_method} ... (sym $_method_name))'
|
|
22
|
+
def_node_matcher :qualifier?, <<-PATTERN
|
|
23
|
+
(send nil? {#{QUALIFIERS.map(&:inspect).join(' ')}}
|
|
24
|
+
... (sym $_method_name))
|
|
25
|
+
PATTERN
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
# Our namespace
|
|
5
|
+
module OrderedMethods
|
|
6
|
+
PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze
|
|
7
|
+
CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze
|
|
8
|
+
|
|
9
|
+
def self.inject_defaults!
|
|
10
|
+
path = CONFIG_DEFAULT.to_s
|
|
11
|
+
hash = ConfigLoader.send(:load_yaml_configuration, path)
|
|
12
|
+
config = Config.new(hash, path)
|
|
13
|
+
puts "configuration from #{path}" if ConfigLoader.debug?
|
|
14
|
+
config = ConfigLoader.merge_with_default(config, path)
|
|
15
|
+
ConfigLoader.instance_variable_set(:@default_configuration, config)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,31 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
lib = File.expand_path('lib', __dir__)
|
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
5
|
|
|
4
6
|
Gem::Specification.new do |spec|
|
|
5
|
-
spec.name
|
|
6
|
-
spec.version
|
|
7
|
-
spec.authors
|
|
8
|
-
spec.email
|
|
7
|
+
spec.name = 'rubocop-ordered_methods'
|
|
8
|
+
spec.version = '0.7'
|
|
9
|
+
spec.authors = ['Shane Cavanaugh']
|
|
10
|
+
spec.email = ['shane@shanecav.net']
|
|
9
11
|
|
|
10
|
-
spec.summary
|
|
11
|
-
spec.homepage
|
|
12
|
-
spec.license
|
|
12
|
+
spec.summary = 'Checks that methods are ordered alphabetically.'
|
|
13
|
+
spec.homepage = 'https://github.com/shanecav84/rubocop-ordered_methods'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 2.4'
|
|
13
16
|
|
|
14
17
|
# Specify which files should be added to the gem when it is released.
|
|
15
18
|
# The `git ls-files -z` loads the files in the RubyGem that have been added
|
|
16
19
|
# into git.
|
|
17
|
-
spec.files
|
|
20
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
18
21
|
`git ls-files -z`.split("\x0").reject do |f|
|
|
19
22
|
f.match(%r{^(test|spec|features)/})
|
|
20
23
|
end
|
|
21
24
|
end
|
|
22
|
-
spec.bindir
|
|
23
|
-
spec.executables
|
|
25
|
+
spec.bindir = 'exe'
|
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
24
27
|
spec.require_paths = ['lib']
|
|
25
28
|
|
|
26
|
-
spec.add_runtime_dependency 'rubocop', '
|
|
29
|
+
spec.add_runtime_dependency 'rubocop', '>= 1.0'
|
|
27
30
|
|
|
28
|
-
spec.add_development_dependency 'bundler'
|
|
29
|
-
spec.add_development_dependency 'rake', '~>
|
|
31
|
+
spec.add_development_dependency 'bundler'
|
|
32
|
+
spec.add_development_dependency 'rake', '~> 12.3.3'
|
|
30
33
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
31
34
|
end
|
metadata
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
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.7'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shane Cavanaugh
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-01-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rubocop
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0
|
|
19
|
+
version: '1.0'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0
|
|
26
|
+
version: '1.0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: bundler
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
33
|
+
version: '0'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - "
|
|
38
|
+
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
40
|
+
version: '0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rake
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version:
|
|
47
|
+
version: 12.3.3
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version:
|
|
54
|
+
version: 12.3.3
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: rspec
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -66,7 +66,7 @@ dependencies:
|
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '3.0'
|
|
69
|
-
description:
|
|
69
|
+
description:
|
|
70
70
|
email:
|
|
71
71
|
- shane@shanecav.net
|
|
72
72
|
executables: []
|
|
@@ -74,24 +74,30 @@ extensions: []
|
|
|
74
74
|
extra_rdoc_files: []
|
|
75
75
|
files:
|
|
76
76
|
- ".gitignore"
|
|
77
|
+
- ".rakeTasks"
|
|
77
78
|
- ".rubocop.yml"
|
|
78
79
|
- ".rubocop_todo.yml"
|
|
79
80
|
- ".travis.yml"
|
|
81
|
+
- CHANGELOG.md
|
|
80
82
|
- CODE_OF_CONDUCT.md
|
|
81
83
|
- Gemfile
|
|
82
84
|
- LICENSE.txt
|
|
83
85
|
- README.md
|
|
84
86
|
- Rakefile
|
|
85
87
|
- bin/console
|
|
88
|
+
- config/default.yml
|
|
86
89
|
- lib/rubocop-ordered_methods.rb
|
|
90
|
+
- lib/rubocop/cop/alias_method_order_verifier.rb
|
|
87
91
|
- lib/rubocop/cop/correctors/ordered_methods_corrector.rb
|
|
88
92
|
- lib/rubocop/cop/layout/ordered_methods.rb
|
|
93
|
+
- lib/rubocop/cop/qualifier_node_matchers.rb
|
|
94
|
+
- lib/rubocop/ordered_methods.rb
|
|
89
95
|
- rubocop-ordered_methods.gemspec
|
|
90
96
|
homepage: https://github.com/shanecav84/rubocop-ordered_methods
|
|
91
97
|
licenses:
|
|
92
98
|
- MIT
|
|
93
99
|
metadata: {}
|
|
94
|
-
post_install_message:
|
|
100
|
+
post_install_message:
|
|
95
101
|
rdoc_options: []
|
|
96
102
|
require_paths:
|
|
97
103
|
- lib
|
|
@@ -99,15 +105,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
99
105
|
requirements:
|
|
100
106
|
- - ">="
|
|
101
107
|
- !ruby/object:Gem::Version
|
|
102
|
-
version: '
|
|
108
|
+
version: '2.4'
|
|
103
109
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
110
|
requirements:
|
|
105
111
|
- - ">="
|
|
106
112
|
- !ruby/object:Gem::Version
|
|
107
113
|
version: '0'
|
|
108
114
|
requirements: []
|
|
109
|
-
rubygems_version: 3.
|
|
110
|
-
signing_key:
|
|
115
|
+
rubygems_version: 3.1.2
|
|
116
|
+
signing_key:
|
|
111
117
|
specification_version: 4
|
|
112
118
|
summary: Checks that methods are ordered alphabetically.
|
|
113
119
|
test_files: []
|