rubocop-ordered_methods 0.3 → 0.8

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 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: []