rubocop-ordered_methods 0.4 → 0.5
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/.rubocop.yml +3 -0
- data/.travis.yml +0 -1
- data/CHANGELOG.md +11 -0
- data/README.md +14 -14
- data/lib/rubocop/cop/alias_method_order_verifier.rb +67 -0
- data/lib/rubocop/cop/correctors/ordered_methods_corrector.rb +50 -95
- data/lib/rubocop/cop/layout/ordered_methods.rb +17 -6
- data/lib/rubocop/cop/qualifier_node_matchers.rb +28 -0
- data/rubocop-ordered_methods.gemspec +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5666abbd94c131384aa150fd5d1065c26a17c937b924b0bac4bc7142055a4528
|
4
|
+
data.tar.gz: dc127d1fe270e7c41037218ccfd7cba20297dee56fc59b1998188530ce3ef564
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cfbc383385af0d961764fa99886da093636f26a17271541fae6aa050a1dfc65518fe4a0c9a1ec0c069e86cad3838d2394e22ae2630a2b547e4bd8bb0f823e81
|
7
|
+
data.tar.gz: 56e6d697ee553d9a362b12f009154b0df809dbc67b1a4232082dfe1a03e1401591231cbbffea68d5e1515886151827c54eb47476c9c542e28b6692bf777a0a73
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [0.5] - 2019-11-05
|
10
|
+
|
11
|
+
### Removed
|
12
|
+
|
13
|
+
- Drop Ruby 2.2 support
|
14
|
+
|
15
|
+
### Changed
|
16
|
+
|
17
|
+
- Nonadjacent qualifiers are now autocorrected (#4). Thanks @adamkiczula.
|
18
|
+
- Cache AST traversals for significant speed up on large files
|
19
|
+
|
9
20
|
## [0.4] - 2019-06-11
|
10
21
|
|
11
22
|
### Changed
|
data/README.md
CHANGED
@@ -3,33 +3,33 @@
|
|
3
3
|
|
4
4
|
# RuboCop OrderedMethods
|
5
5
|
|
6
|
-
Check that methods are defined alphabetically
|
7
|
-
autocorrection.
|
6
|
+
Check that methods are defined alphabetically per access modifier block (class,
|
7
|
+
public, private, protected). Includes [autocorrection](#corrector).
|
8
8
|
|
9
9
|
```ruby
|
10
10
|
# bad
|
11
|
-
def self.
|
12
|
-
def self.
|
11
|
+
def self.b_class; end
|
12
|
+
def self.a_class; end
|
13
13
|
|
14
|
-
def
|
15
|
-
def
|
14
|
+
def b_public; end
|
15
|
+
def a_public; end
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
|
-
def
|
20
|
-
def
|
19
|
+
def b_private; end
|
20
|
+
def a_private; end
|
21
21
|
|
22
22
|
# good
|
23
|
-
def self.
|
24
|
-
def self.
|
23
|
+
def self.a_class; end
|
24
|
+
def self.b_class; end
|
25
25
|
|
26
|
-
def
|
27
|
-
def
|
26
|
+
def a_public; end
|
27
|
+
def b_public; end
|
28
28
|
|
29
29
|
private
|
30
30
|
|
31
|
-
def
|
32
|
-
def
|
31
|
+
def a_private; end
|
32
|
+
def b_private; end
|
33
33
|
```
|
34
34
|
|
35
35
|
## Installation
|
@@ -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,120 +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 = %i[
|
18
|
-
alias_method
|
19
|
-
module_function
|
20
|
-
private_class_method
|
21
|
-
public_class_method
|
22
|
-
private
|
23
|
-
protected
|
24
|
-
public
|
25
|
-
].freeze
|
26
|
-
|
27
|
-
def_node_matcher :alias?, '(:alias ... (sym $_method_name))'
|
28
|
-
def_node_matcher :qualifier?, <<-PATTERN
|
29
|
-
(send nil? {#{QUALIFIERS.map(&:inspect).join(' ')}}
|
30
|
-
... (sym $_method_name))
|
31
|
-
PATTERN
|
32
|
-
|
33
|
-
def correct(processed_source, node, previous_node)
|
34
|
-
@processed_source = processed_source
|
35
|
-
@current_node = node
|
36
|
-
@previous_node = previous_node
|
13
|
+
def initialize(comments, siblings)
|
14
|
+
@comments = comments
|
15
|
+
@siblings = siblings
|
16
|
+
end
|
37
17
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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)
|
45
25
|
end
|
26
|
+
end
|
46
27
|
|
47
|
-
|
28
|
+
private
|
48
29
|
|
49
|
-
|
50
|
-
|
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])
|
51
35
|
|
52
|
-
|
36
|
+
last_qualifier_index -= 1
|
53
37
|
end
|
54
38
|
|
55
|
-
|
56
|
-
|
57
|
-
source_range = source_range.join(comment.loc.expression)
|
58
|
-
end
|
59
|
-
source_range
|
60
|
-
end
|
39
|
+
last_qualifier_index
|
40
|
+
end
|
61
41
|
|
62
|
-
|
63
|
-
|
64
|
-
preceding_qualifier_index = node.sibling_index
|
65
|
-
while found_qualifier?(node, siblings[preceding_qualifier_index + 1])
|
66
|
-
source_range = source_range.join(
|
67
|
-
siblings[preceding_qualifier_index + 1].source_range
|
68
|
-
)
|
69
|
-
preceding_qualifier_index += 1
|
70
|
-
end
|
71
|
-
source_range
|
72
|
-
end
|
42
|
+
def found_qualifier?(node, next_sibling)
|
43
|
+
return false if next_sibling.nil?
|
73
44
|
|
74
|
-
|
75
|
-
|
76
|
-
node,
|
77
|
-
node.source_range
|
78
|
-
)
|
79
|
-
join_comments(node, with_modifiers_and_aliases)
|
80
|
-
end
|
81
|
-
|
82
|
-
# We don't want a method to be defined after its alias
|
83
|
-
def moving_after_alias?(current_node, previous_node)
|
84
|
-
siblings = current_node.parent.children
|
85
|
-
current_node_aliases = siblings.select do |sibling|
|
86
|
-
alias?(sibling) == current_node.method_name
|
87
|
-
end
|
88
|
-
filter = current_node_aliases.delete_if do |cna|
|
89
|
-
cna.sibling_index == current_node.sibling_index + 1
|
90
|
-
end
|
91
|
-
return false if filter.empty?
|
45
|
+
(qualifier?(next_sibling) || alias?(next_sibling)) == node.method_name
|
46
|
+
end
|
92
47
|
|
93
|
-
|
94
|
-
|
95
|
-
|
48
|
+
def join_comments(node, source_range)
|
49
|
+
@comments[node].each do |comment|
|
50
|
+
source_range = source_range.join(comment.loc.expression)
|
96
51
|
end
|
52
|
+
source_range
|
53
|
+
end
|
97
54
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
)
|
107
|
-
end
|
108
|
-
if moving_after_alias?(@previous_node, @current_node)
|
109
|
-
ignore_node(@previous_node)
|
110
|
-
raise Warning, format(
|
111
|
-
ALIAS_BEFORE_METHOD_WARNING_FMT,
|
112
|
-
first_method_name: @previous_node.method_name,
|
113
|
-
second_method_name: @current_node.method_name
|
114
|
-
)
|
115
|
-
end
|
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
|
116
63
|
end
|
117
|
-
|
64
|
+
source_range
|
65
|
+
end
|
66
|
+
|
67
|
+
def join_surroundings(node)
|
68
|
+
with_modifiers_and_aliases = join_modifiers_and_aliases(
|
69
|
+
node,
|
70
|
+
node.source_range
|
71
|
+
)
|
72
|
+
join_comments(node, with_modifiers_and_aliases)
|
118
73
|
end
|
119
74
|
end
|
120
75
|
end
|
@@ -42,15 +42,12 @@ module RuboCop
|
|
42
42
|
"#{cop_name}. Expected one of: #{COMPARISONS.keys.join(', ')}".freeze
|
43
43
|
|
44
44
|
def autocorrect(node)
|
45
|
-
|
46
|
-
processed_source,
|
47
|
-
node,
|
48
|
-
@previous_node
|
49
|
-
)
|
45
|
+
@corrector.correct(node, @previous_node)
|
50
46
|
end
|
51
47
|
|
52
48
|
def on_begin(node)
|
53
|
-
|
49
|
+
cache(node)
|
50
|
+
consecutive_methods(@siblings) do |previous, current|
|
54
51
|
unless ordered?(previous, current)
|
55
52
|
@previous_node = previous
|
56
53
|
add_offense(
|
@@ -70,6 +67,20 @@ module RuboCop
|
|
70
67
|
(node.send_type? && node.bare_access_modifier?)
|
71
68
|
end
|
72
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
|
+
|
73
84
|
def consecutive_methods(nodes)
|
74
85
|
filtered = filter_relevant_nodes(nodes)
|
75
86
|
filtered_and_grouped = group_methods_by_access_modifier(filtered)
|
@@ -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
|
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.5'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shane Cavanaugh
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -86,8 +86,10 @@ files:
|
|
86
86
|
- bin/console
|
87
87
|
- config/default.yml
|
88
88
|
- lib/rubocop-ordered_methods.rb
|
89
|
+
- lib/rubocop/cop/alias_method_order_verifier.rb
|
89
90
|
- lib/rubocop/cop/correctors/ordered_methods_corrector.rb
|
90
91
|
- lib/rubocop/cop/layout/ordered_methods.rb
|
92
|
+
- lib/rubocop/cop/qualifier_node_matchers.rb
|
91
93
|
- lib/rubocop/ordered_methods.rb
|
92
94
|
- rubocop-ordered_methods.gemspec
|
93
95
|
homepage: https://github.com/shanecav84/rubocop-ordered_methods
|