rubocop-ordered_methods 0.3 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33871b68e39c03de6c12f462dc732d282489b190bdaedca681f955c60a27c20c
4
- data.tar.gz: c9c22948ef1db00f774d8fcfdf0cd2f60422da6c44b16a3e9430bdef42c86efb
3
+ metadata.gz: fc5f933eab16f22d4ce9e90bac7b7da25af7af45f7fd1204974ea26d98287476
4
+ data.tar.gz: c3e5a535a8667acf2c88e8c127219b8b8e330d10e6575df5748391ec1c7758ba
5
5
  SHA512:
6
- metadata.gz: 571d2b28004397aff91256be2d4b153255870d5b7a4bd8877c3956003e3d73959e5bca95fa7b26901ccf43ee343a5b722eae24dea79540948cbe48a3d016d3bb
7
- data.tar.gz: 3fe6b38928ed8c4ee6b5c08d27e3ba4e84277f98e7dfa9fe2e74cca570874b4f63caed8ba40ef5e8799d22bd6ae39db4a619beaddde5cc5328d9685e02525809
6
+ metadata.gz: c83ba399a7357517935466f59e4be28b75fbb399a571041b54ba4be1c387797b1867be69fcac2abe8e60e89572b34d35d9a327a171880cec2d9807ee258766ca
7
+ data.tar.gz: dc2897b646af1eb6e2b84dbe2e693be8a0a48de8645caf9551557c6dfe36809a34c92c4166428f9f0b17bd541c3a5c8bf60d349ea3db3286c09ebb4897467e7e
data/.gitignore CHANGED
@@ -8,3 +8,4 @@
8
8
  /tmp/
9
9
 
10
10
  Gemfile.lock
11
+ .ruby-version
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
@@ -2,10 +2,19 @@ inherit_from: .rubocop_todo.yml
2
2
 
3
3
  require: rubocop-ordered_methods
4
4
 
5
+ AllCops:
6
+ NewCops: enable
7
+ SuggestExtensions: false
8
+ TargetRubyVersion: 2.4
9
+
5
10
  Metrics/BlockLength:
6
11
  Exclude:
7
12
  - spec/**/*
8
13
 
14
+ Metrics/MethodLength:
15
+ Exclude:
16
+ - spec/**/*
17
+
9
18
  Naming/FileName:
10
19
  Exclude:
11
20
  - lib/rubocop-ordered_methods.rb
data/.rubocop_todo.yml CHANGED
@@ -1,21 +1,24 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2019-02-17 13:54:25 -0500 using RuboCop version 0.64.0.
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
- Metrics/AbcSize:
11
- Max: 17
10
+ # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
11
+ Metrics/MethodLength:
12
+ Max: 11
12
13
 
13
14
  # Offense count: 1
14
- # Configuration parameters: CountComments.
15
- Metrics/ClassLength:
16
- Max: 101
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
- # Configuration parameters: CountComments, ExcludedMethods.
20
- Metrics/MethodLength:
21
- Max: 11
21
+ # Cop supports --auto-correct.
22
+ Style/RedundantFreeze:
23
+ Exclude:
24
+ - 'lib/rubocop/cop/layout/ordered_methods.rb'
data/.travis.yml CHANGED
@@ -3,9 +3,10 @@ sudo: false
3
3
  language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
- - 2.2
7
6
  - 2.3
8
7
  - 2.4
9
8
  - 2.5
10
9
  - 2.6
11
- before_install: gem install bundler -v 1.17.2
10
+ script: bundle exec rake
11
+ before_install:
12
+ - gem install bundler || gem install bundler --version '< 2'
data/CHANGELOG.md ADDED
@@ -0,0 +1,69 @@
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
+ ## [0.8] - 2021-02-01
10
+
11
+ ### Fixed
12
+
13
+ - Fix NoMethodError and the "\[Correctable\]" label ([#6](https://github.com/shanecav84/rubocop-ordered_methods/pull/6)). Thanks @jaredbeck.
14
+
15
+ ## [0.7] - 2021-01-11
16
+
17
+ ### Removed
18
+
19
+ - Drop Ruby 2.3 support
20
+ - Drop support for rubocop < 1.0
21
+
22
+ ### Changed
23
+
24
+ - Support for rubocop >= 1.0 ([#5](https://github.com/shanecav84/rubocop-ordered_methods/pull/5)). Thanks @jaredbeck.
25
+
26
+ ## [0.6] - 2020-03-01
27
+
28
+ ### Security
29
+
30
+ - Upgrade rake to avoid vulnerability https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-8130
31
+ - rake is a development dependency for this gem, so shouldn't have been a risk for production
32
+
33
+ ## [0.5] - 2019-11-05
34
+
35
+ ### Removed
36
+
37
+ - Drop Ruby 2.2 support
38
+
39
+ ### Changed
40
+
41
+ - Nonadjacent qualifiers are now autocorrected (#4). Thanks @adamkiczula.
42
+ - Cache AST traversals for significant speed up on large files
43
+
44
+ ## [0.4] - 2019-06-11
45
+
46
+ ### Changed
47
+
48
+ - More robust autocorrection of a method and its surroundings (see `Corrector` in the `README`).
49
+
50
+ ## [0.3] - 2019-02-17
51
+
52
+ ### Added
53
+
54
+ - Configuration defaults
55
+
56
+ ## [0.2] - 2019-02-17
57
+
58
+ ### Added
59
+
60
+ - Autocorrector
61
+
62
+ ## [0.1] - 2019-02-17
63
+
64
+ Initial release.
65
+
66
+ [Unreleased]: https://github.com/shanecav84/rubocop-ordered_methods/compare/v0.3...HEAD
67
+ [0.3]: https://github.com/shanecav84/rubocop-ordered_methods/compare/v0.2...v0.3
68
+ [0.2]: https://github.com/shanecav84/rubocop-ordered_methods/compare/v0.1...v0.2
69
+ [0.1]: https://github.com/shanecav84/rubocop-ordered_methods/releases/tag/v0.1
data/Gemfile CHANGED
@@ -1,6 +1,5 @@
1
- source 'https://rubygems.org'
1
+ # frozen_string_literal: true
2
2
 
3
- git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
3
+ source 'https://rubygems.org'
4
4
 
5
- # Specify your gem's dependencies in rubocop-ordered_methods.gemspec
6
5
  gemspec
data/README.md CHANGED
@@ -1,32 +1,35 @@
1
+ [![Gem Version](https://badge.fury.io/rb/rubocop-ordered_methods.svg)](https://badge.fury.io/rb/rubocop-ordered_methods)
2
+ [![Build Status](https://travis-ci.org/shanecav84/rubocop-ordered_methods.svg?branch=master)](https://travis-ci.org/shanecav84/rubocop-ordered_methods)
3
+
1
4
  # RuboCop OrderedMethods
2
5
 
3
- Check that methods are defined alphabetically. Note [caveats](#caveats) for
4
- autocorrector.
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.b; end
9
- def self.a; end
11
+ def self.b_class; end
12
+ def self.a_class; end
10
13
 
11
- def b; end
12
- def a; end
14
+ def b_public; end
15
+ def a_public; end
13
16
 
14
17
  private
15
18
 
16
- def d; end
17
- def c; end
19
+ def b_private; end
20
+ def a_private; end
18
21
 
19
22
  # good
20
- def self.a; end
21
- def self.b; end
23
+ def self.a_class; end
24
+ def self.b_class; end
22
25
 
23
- def a; end
24
- def b; end
26
+ def a_public; end
27
+ def b_public; end
25
28
 
26
29
  private
27
30
 
28
- def c; end
29
- def d; end
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 three
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 alphabetically. It attempts to
79
- include surrounding comments and the qualifiers listed in
80
- `::RuboCop::Cop::Layout::OrderedMethods::QUALIFIERS`.
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
- The corrector can fail to include surrounding comments and qualifiers for some
84
- methods.
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 https://github.com/shanecav84/rubocop-ordered_methods. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
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 [MIT License](https://opensource.org/licenses/MIT).
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 trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/shanecav84/rubocop-ordered_methods/blob/master/CODE_OF_CONDUCT.md).
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rubocop/rake_task'
3
5
  require 'rspec/core/rake_task'
data/bin/console CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'rubocop/ordered_methods'
data/config/default.yml CHANGED
@@ -1,4 +1,6 @@
1
1
  ---
2
2
  Layout/OrderedMethods:
3
+ Enabled: true
4
+ EnforcedStyle: 'alphabetical'
3
5
  IgnoredMethods:
4
6
  - initialize
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rubocop'
2
4
  require_relative 'rubocop/ordered_methods'
3
5
  require_relative 'rubocop/cop/layout/ordered_methods'
@@ -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
- class << self
10
- include IgnoredNode
11
- extend NodePattern::Macros
11
+ include QualifierNodeMatchers
12
12
 
13
- ALIAS_BEFORE_METHOD_WARNING_FMT = "Won't reorder " \
14
- '%<first_method_name>s and %<second_method_name>s because ' \
15
- 'alias for %<first_method_name>s would be declared before ' \
16
- 'its method definition.'.freeze
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
- verify_alias_method_order
35
- current_range = with_surroundings(@current_node)
36
- previous_range = with_surroundings(@previous_node)
37
- lambda do |corrector|
38
- corrector.replace(current_range, previous_range.source)
39
- corrector.replace(previous_range, current_range.source)
40
- end
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
- private
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
- # We don't want a method to be defined after its alias
50
- def moving_after_alias?(current_node, previous_node)
51
- siblings = current_node.parent.children
52
- current_node_aliases = siblings.select do |sibling|
53
- alias?(sibling) == current_node.method_name
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
- current_node_aliases.any? do |cna|
61
- previous_node.sibling_index > cna.sibling_index
62
- end
36
+ last_qualifier_index -= 1
63
37
  end
64
38
 
65
- # rubocop:disable Metrics/MethodLength, Style/GuardClause
66
- def verify_alias_method_order
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
- def with_comments(node)
87
- node.source_range
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
- def with_modifiers_and_aliases(node)
93
- surrounding_range = node.source_range
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
- def with_preceding_comments(node)
104
- surrounding_range = node.source_range
105
- @processed_source.ast_with_comments[node].each do |comment|
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
- def with_succeeding_comments(node)
112
- surrounding_range = node.source_range
113
- @processed_source.each_comment do |comment|
114
- if comment.loc.expression.begin_pos == surrounding_range.end_pos + 1
115
- surrounding_range = surrounding_range.join(comment.loc.expression)
116
- end
117
- end
118
- surrounding_range
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
- def with_surroundings(node)
67
+ def join_surroundings(node)
68
+ with_modifiers_and_aliases = join_modifiers_and_aliases(
69
+ node,
122
70
  node.source_range
123
- .join(with_comments(node))
124
- .join(with_modifiers_and_aliases(node))
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
- # Check that methods are defined alphabetically.
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
@@ -30,101 +30,109 @@ module RuboCop
30
30
  # def c; end
31
31
  # def d; end
32
32
  class OrderedMethods < Cop
33
+ # TODO: Extending Cop is deprecated. Should extend Cop::Base.
33
34
  include IgnoredMethods
34
35
  include RangeHelp
35
36
 
36
- MSG = 'Methods should be sorted alphabetically.'.freeze
37
- VISIBILITY_MODIFIERS = %i[
38
- module_function
39
- private
40
- protected
41
- public
42
- ].freeze
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
37
+ COMPARISONS = {
38
+ 'alphabetical' => lambda do |left_method, right_method|
39
+ (left_method.method_name <=> right_method.method_name) != 1
40
+ end
41
+ }.freeze
42
+ ERR_INVALID_COMPARISON = 'Invalid "Comparison" config for ' \
43
+ "#{cop_name}. Expected one of: #{COMPARISONS.keys.join(', ')}".freeze
49
44
 
50
45
  def autocorrect(node)
51
- OrderedMethodsCorrector.correct(
52
- processed_source,
53
- node,
54
- @previous_node
55
- )
46
+ @corrector.correct(node, @previous_node)
56
47
  end
57
48
 
58
49
  def on_begin(node)
59
- consecutive_methods(node.children) do |previous, current|
50
+ cache(node)
51
+ consecutive_methods(@siblings) do |previous, current|
60
52
  unless ordered?(previous, current)
61
53
  @previous_node = previous
62
- add_offense(current)
54
+ add_offense(
55
+ current,
56
+ message: 'Methods should be sorted in ' \
57
+ "#{cop_config['EnforcedStyle']} order."
58
+ )
63
59
  end
64
60
  end
65
61
  end
66
62
 
67
63
  private
68
64
 
69
- def consecutive_methods(ast)
70
- filtered_and_grouped(ast).each do |method_group|
65
+ def access_modified?(node, is_class_method_block)
66
+ (node.defs_type? && !is_class_method_block) ||
67
+ (node.def_type? && is_class_method_block) ||
68
+ (node.send_type? && node.bare_access_modifier?)
69
+ end
70
+
71
+ # Cache to avoid traversing the AST multiple times
72
+ def cache(node)
73
+ @cache ||= begin
74
+ @siblings = node.children
75
+
76
+ # Init the corrector with the cache to avoid traversing the AST in
77
+ # the corrector. We always init the @corrector, even if
78
+ # @options[:auto_correct] is nil, because `add_offense` always
79
+ # attempts correction. This correction attempt is how RuboCop knows
80
+ # if the offense can be labeled "[Correctable]".
81
+ comments = processed_source.ast_with_comments
82
+ @corrector = OrderedMethodsCorrector.new(comments, @siblings)
83
+ end
84
+ end
85
+
86
+ # We disable `Style/ExplicitBlockArgument` for performance. See
87
+ # https://github.com/shanecav84/rubocop-ordered_methods/pull/5#pullrequestreview-562957146
88
+ # rubocop:disable Style/ExplicitBlockArgument
89
+ def consecutive_methods(nodes)
90
+ filtered = filter_relevant_nodes(nodes)
91
+ filtered_and_grouped = group_methods_by_access_modifier(filtered)
92
+ filtered_and_grouped.each do |method_group|
71
93
  method_group.each_cons(2) do |left_method, right_method|
72
94
  yield left_method, right_method
73
95
  end
74
96
  end
75
97
  end
98
+ # rubocop:enable Style/ExplicitBlockArgument
76
99
 
77
100
  def filter_relevant_nodes(nodes)
78
101
  nodes.select do |node|
79
102
  (
80
- class_def?(node) ||
81
- instance_def?(node) ||
82
- visibility_modifier?(node)
83
- ) && !ignored_method?(node.method_name)
103
+ (node.defs_type? || node.def_type?) &&
104
+ !ignored_method?(node.method_name)
105
+ ) || (node.send_type? && node.bare_access_modifier?)
84
106
  end
85
107
  end
86
108
 
87
- def filtered_and_grouped(ast)
88
- group_methods_by_visiblity_block(filter_relevant_nodes(ast))
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
109
+ # Group methods by the access modifier block they are declared in.
110
+ # Multiple blocks of the same modifier will have their methods grouped
93
111
  # separately; for example, the following would be separated into two
94
112
  # groups:
95
113
  # private
96
114
  # def a; end
97
115
  # private
98
116
  # def b; end
99
- # rubocop:disable Metrics/MethodLength
100
- def group_methods_by_visiblity_block(nodes)
117
+ def group_methods_by_access_modifier(nodes)
101
118
  is_class_method_block = false
119
+
102
120
  nodes.each_with_object([[]]) do |node, grouped_methods|
103
- if new_visiblity_block?(node, is_class_method_block)
121
+ if access_modified?(node, is_class_method_block)
104
122
  grouped_methods << []
105
123
  end
106
-
107
- is_class_method_block = true if class_def?(node)
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
124
+ is_class_method_block = node.defs_type?
125
+ next if node.send_type? && node.bare_access_modifier?
114
126
 
115
127
  grouped_methods.last << node
116
128
  end
117
129
  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
130
 
126
131
  def ordered?(left_method, right_method)
127
- (left_method.method_name <=> right_method.method_name) != 1
132
+ comparison = COMPARISONS[cop_config['EnforcedStyle']]
133
+ raise Error, ERR_INVALID_COMPARISON if comparison.nil?
134
+
135
+ comparison.call(left_method, right_method)
128
136
  end
129
137
  end
130
138
  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
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RuboCop
4
+ # Our namespace
2
5
  module OrderedMethods
3
6
  PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze
4
- CONFIG_DEFAULT = PROJECT_ROOT.join("config", "default.yml").freeze
7
+ CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze
5
8
 
6
9
  def self.inject_defaults!
7
10
  path = CONFIG_DEFAULT.to_s
@@ -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 = 'rubocop-ordered_methods'
6
- spec.version = '0.3'
7
- spec.authors = ['Shane Cavanaugh']
8
- spec.email = ['shane@shanecav.net']
7
+ spec.name = 'rubocop-ordered_methods'
8
+ spec.version = '0.8'
9
+ spec.authors = ['Shane Cavanaugh']
10
+ spec.email = ['shane@shanecav.net']
9
11
 
10
- spec.summary = 'Checks that methods are ordered alphabetically.'
11
- spec.homepage = 'https://github.com/shanecav84/rubocop-ordered_methods'
12
- spec.license = 'MIT'
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 = Dir.chdir(File.expand_path(__dir__)) do
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 = 'exe'
23
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
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', '~> 0.6'
29
+ spec.add_runtime_dependency 'rubocop', '>= 1.0'
27
30
 
28
- spec.add_development_dependency 'bundler', '~> 1.17'
29
- spec.add_development_dependency 'rake', '~> 10.0'
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.3'
4
+ version: '0.8'
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: 2019-02-17 00:00:00.000000000 Z
11
+ date: 2021-03-01 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.6'
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.6'
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: '1.17'
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: '1.17'
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: '10.0'
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: '10.0'
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,9 +74,11 @@ 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
@@ -85,15 +87,17 @@ files:
85
87
  - bin/console
86
88
  - config/default.yml
87
89
  - lib/rubocop-ordered_methods.rb
90
+ - lib/rubocop/cop/alias_method_order_verifier.rb
88
91
  - lib/rubocop/cop/correctors/ordered_methods_corrector.rb
89
92
  - lib/rubocop/cop/layout/ordered_methods.rb
93
+ - lib/rubocop/cop/qualifier_node_matchers.rb
90
94
  - lib/rubocop/ordered_methods.rb
91
95
  - rubocop-ordered_methods.gemspec
92
96
  homepage: https://github.com/shanecav84/rubocop-ordered_methods
93
97
  licenses:
94
98
  - MIT
95
99
  metadata: {}
96
- post_install_message:
100
+ post_install_message:
97
101
  rdoc_options: []
98
102
  require_paths:
99
103
  - lib
@@ -101,15 +105,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
101
105
  requirements:
102
106
  - - ">="
103
107
  - !ruby/object:Gem::Version
104
- version: '0'
108
+ version: '2.4'
105
109
  required_rubygems_version: !ruby/object:Gem::Requirement
106
110
  requirements:
107
111
  - - ">="
108
112
  - !ruby/object:Gem::Version
109
113
  version: '0'
110
114
  requirements: []
111
- rubygems_version: 3.0.1
112
- signing_key:
115
+ rubygems_version: 3.1.2
116
+ signing_key:
113
117
  specification_version: 4
114
118
  summary: Checks that methods are ordered alphabetically.
115
119
  test_files: []