rubocop-ordered_methods 0.1 → 0.2

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: ade6d192050ac40f268177e3ede23b40f57d569041c6191baa855bfcef87a2c2
4
- data.tar.gz: b39ded0724baf7c35b2d48506bebbe0924a04be6fe0c300a75090bf7e9deb7af
3
+ metadata.gz: efe0a069919334996c9317cf8d9dd03bb19fe984a9d8d7a294f017dcb361ec96
4
+ data.tar.gz: b8c6b15fbfa6d2b44c99b051ebfb4a2ba047c2958f16cf9015b4f2d87f674fe5
5
5
  SHA512:
6
- metadata.gz: 79368459e3709585a1741e6d5374b5e9d5176562f494a344ceed58208c512bf8c9f324ef8200bd9de9645b95a2d6a05d4bc584af97329997328bad44db2426ff
7
- data.tar.gz: 1c3dcbf99709710ad10fec4e0085f1fd8caf9094082d27cb8a8b77fc6e081d0942bbfd41953b2bd715d184d3430a92ee463665913c51fcfcdac483c141a69f89
6
+ metadata.gz: cca41398955b51c5d968fc84b4ec0833339224c696de865d6421834491da2113b12d7e4bfce8fe1771b53f18a0ae872e350ffff96fccce4610b71eca38b3583d
7
+ data.tar.gz: 57f61650ad8df63193aa45f9fa35133c85698a134d9a6ee3bfa305b9de074763cc45d7fc26a64da216ba79f86d5b19e5fec84084ee989f266e82dc56251f00fd
@@ -1,3 +1,5 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
1
3
  require: rubocop-ordered_methods
2
4
 
3
5
  Metrics/BlockLength:
@@ -0,0 +1,21 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2019-02-17 13:54:25 -0500 using RuboCop version 0.64.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ Metrics/AbcSize:
11
+ Max: 17
12
+
13
+ # Offense count: 1
14
+ # Configuration parameters: CountComments.
15
+ Metrics/ClassLength:
16
+ Max: 101
17
+
18
+ # Offense count: 1
19
+ # Configuration parameters: CountComments, ExcludedMethods.
20
+ Metrics/MethodLength:
21
+ Max: 11
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # RuboCop OrderedMethods
2
2
 
3
- Check that methods are defined alphabetically.
3
+ Check that methods are defined alphabetically. Note [caveats](#caveats) for
4
+ autocorrector.
4
5
 
5
6
  ```ruby
6
7
  # bad
@@ -72,6 +73,16 @@ Name | Default value | Configurable values
72
73
  --- | --- | ---
73
74
  IgnoredMethods | `initialize` | Array
74
75
 
76
+ ### Corrector
77
+
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`.
81
+
82
+ #### Caveats
83
+ The corrector can fail to include surrounding comments and qualifiers for some
84
+ methods.
85
+
75
86
  ## Development
76
87
 
77
88
  ### Setup
@@ -1,2 +1,3 @@
1
1
  require 'rubocop'
2
2
  require_relative 'rubocop/cop/layout/ordered_methods'
3
+ require_relative 'rubocop/cop/correctors/ordered_methods_corrector'
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../layout/ordered_methods'
4
+
5
+ module RuboCop
6
+ module Cop
7
+ # This auto-corrects method order
8
+ class OrderedMethodsCorrector
9
+ class << self
10
+ include IgnoredNode
11
+ extend NodePattern::Macros
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
33
+
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
41
+ end
42
+
43
+ private
44
+
45
+ def found_qualifier?(node, next_sibling)
46
+ (qualifier?(next_sibling) || alias?(next_sibling)) == node.method_name
47
+ end
48
+
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?
59
+
60
+ current_node_aliases.any? do |cna|
61
+ previous_node.sibling_index > cna.sibling_index
62
+ end
63
+ end
64
+
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
85
+
86
+ def with_comments(node)
87
+ node.source_range
88
+ .join(with_preceding_comments(node))
89
+ .join(with_succeeding_comments(node))
90
+ end
91
+
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
102
+
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
109
+ end
110
+
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
119
+ end
120
+
121
+ def with_surroundings(node)
122
+ node.source_range
123
+ .join(with_comments(node))
124
+ .join(with_modifiers_and_aliases(node))
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -47,9 +47,20 @@ module RuboCop
47
47
  (send nil? { #{VISIBILITY_MODIFIERS.map(&:inspect).join(' ')} })
48
48
  PATTERN
49
49
 
50
+ def autocorrect(node)
51
+ OrderedMethodsCorrector.correct(
52
+ processed_source,
53
+ node,
54
+ @previous_node
55
+ )
56
+ end
57
+
50
58
  def on_begin(node)
51
59
  consecutive_methods(node.children) do |previous, current|
52
- add_offense(current) unless ordered?(previous, current)
60
+ unless ordered?(previous, current)
61
+ @previous_node = previous
62
+ add_offense(current)
63
+ end
53
64
  end
54
65
  end
55
66
 
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = 'rubocop-ordered_methods'
6
- spec.version = '0.1'
6
+ spec.version = '0.2'
7
7
  spec.authors = ['Shane Cavanaugh']
8
8
  spec.email = ['shane@shanecav.net']
9
9
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-ordered_methods
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Cavanaugh
@@ -75,15 +75,16 @@ extra_rdoc_files: []
75
75
  files:
76
76
  - ".gitignore"
77
77
  - ".rubocop.yml"
78
+ - ".rubocop_todo.yml"
78
79
  - ".travis.yml"
79
80
  - CODE_OF_CONDUCT.md
80
81
  - Gemfile
81
- - Gemfile.lock
82
82
  - LICENSE.txt
83
83
  - README.md
84
84
  - Rakefile
85
85
  - bin/console
86
86
  - lib/rubocop-ordered_methods.rb
87
+ - lib/rubocop/cop/correctors/ordered_methods_corrector.rb
87
88
  - lib/rubocop/cop/layout/ordered_methods.rb
88
89
  - rubocop-ordered_methods.gemspec
89
90
  homepage: https://github.com/shanecav84/rubocop-ordered_methods