leftovers 0.11.1 → 0.12.0

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.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +1 -0
  4. data/docs/Configuration.md +7 -0
  5. data/exe/leftovers +3 -1
  6. data/leftovers.gemspec +3 -4
  7. data/lib/config/activesupport.yml +1 -1
  8. data/lib/config/rspec.yml +21 -0
  9. data/lib/leftovers/ast/array_node.rb +2 -2
  10. data/lib/leftovers/ast/block_node.rb +1 -1
  11. data/lib/leftovers/ast/builder.rb +19 -18
  12. data/lib/leftovers/ast/casgn_node.rb +2 -2
  13. data/lib/leftovers/ast/const_node.rb +1 -1
  14. data/lib/leftovers/ast/def_node.rb +1 -1
  15. data/lib/leftovers/ast/defs_node.rb +1 -1
  16. data/lib/leftovers/ast/false_node.rb +1 -1
  17. data/lib/leftovers/ast/hash_node.rb +2 -2
  18. data/lib/leftovers/ast/module_node.rb +1 -1
  19. data/lib/leftovers/ast/nil_node.rb +1 -1
  20. data/lib/leftovers/ast/node.rb +13 -1
  21. data/lib/leftovers/ast/numeric_node.rb +1 -1
  22. data/lib/leftovers/ast/send_node.rb +16 -3
  23. data/lib/leftovers/ast/str_node.rb +1 -1
  24. data/lib/leftovers/ast/sym_node.rb +1 -1
  25. data/lib/leftovers/ast/true_node.rb +1 -1
  26. data/lib/leftovers/ast/var_node.rb +1 -1
  27. data/lib/leftovers/ast/vasgn_node.rb +2 -2
  28. data/lib/leftovers/ast.rb +2 -21
  29. data/lib/leftovers/autoloader.rb +36 -0
  30. data/lib/leftovers/cli.rb +64 -45
  31. data/lib/leftovers/collection.rb +66 -0
  32. data/lib/leftovers/collector.rb +17 -27
  33. data/lib/leftovers/config.rb +17 -5
  34. data/lib/leftovers/config_loader/attribute.rb +2 -2
  35. data/lib/leftovers/config_loader/bool_schema.rb +21 -0
  36. data/lib/leftovers/config_loader/document_schema.rb +2 -2
  37. data/lib/leftovers/config_loader/inherit_schema_attributes.rb +1 -1
  38. data/lib/leftovers/config_loader/node.rb +8 -8
  39. data/lib/leftovers/config_loader/regexp_schema.rb +1 -1
  40. data/lib/leftovers/config_loader/rule_pattern_schema.rb +1 -0
  41. data/lib/leftovers/config_loader/schema.rb +1 -1
  42. data/lib/leftovers/config_loader/string_enum_schema.rb +1 -1
  43. data/lib/leftovers/config_loader/value_or_array_schema.rb +1 -1
  44. data/lib/leftovers/config_loader.rb +8 -48
  45. data/lib/leftovers/definition.rb +4 -4
  46. data/lib/leftovers/definition_collection.rb +3 -3
  47. data/lib/leftovers/definition_node.rb +2 -2
  48. data/lib/leftovers/definition_node_set.rb +1 -1
  49. data/lib/leftovers/definition_set.rb +4 -4
  50. data/lib/leftovers/definition_to_add.rb +2 -2
  51. data/lib/leftovers/error.rb +6 -0
  52. data/lib/leftovers/file.rb +4 -4
  53. data/lib/leftovers/file_collector/comments_processor.rb +23 -18
  54. data/lib/leftovers/file_collector/node_processor/error.rb +16 -0
  55. data/lib/leftovers/file_collector/node_processor.rb +19 -2
  56. data/lib/leftovers/file_collector.rb +28 -20
  57. data/lib/leftovers/file_list.rb +4 -6
  58. data/lib/leftovers/matcher_builders/and.rb +5 -5
  59. data/lib/leftovers/matcher_builders/document.rb +1 -3
  60. data/lib/leftovers/matcher_builders/name.rb +4 -7
  61. data/lib/leftovers/matcher_builders/node.rb +21 -35
  62. data/lib/leftovers/matcher_builders/node_has_argument.rb +17 -29
  63. data/lib/leftovers/matcher_builders/node_has_block.rb +17 -0
  64. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +7 -9
  65. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +10 -10
  66. data/lib/leftovers/matcher_builders/node_has_receiver.rb +6 -8
  67. data/lib/leftovers/matcher_builders/node_name.rb +3 -5
  68. data/lib/leftovers/matcher_builders/node_pair_key.rb +4 -4
  69. data/lib/leftovers/matcher_builders/node_pair_value.rb +4 -4
  70. data/lib/leftovers/matcher_builders/node_path.rb +3 -4
  71. data/lib/leftovers/matcher_builders/node_privacy.rb +3 -3
  72. data/lib/leftovers/matcher_builders/node_type.rb +18 -13
  73. data/lib/leftovers/matcher_builders/node_value.rb +18 -31
  74. data/lib/leftovers/matcher_builders/or.rb +10 -10
  75. data/lib/leftovers/matcher_builders/path.rb +3 -3
  76. data/lib/leftovers/matcher_builders/string_pattern.rb +2 -0
  77. data/lib/leftovers/matcher_builders/unless.rb +1 -3
  78. data/lib/leftovers/matcher_builders.rb +2 -22
  79. data/lib/leftovers/matchers/node_has_block.rb +13 -0
  80. data/lib/leftovers/matchers/node_scalar_value.rb +1 -1
  81. data/lib/leftovers/matchers.rb +2 -27
  82. data/lib/leftovers/merged_config.rb +16 -17
  83. data/lib/leftovers/parser.rb +1 -1
  84. data/lib/leftovers/precompile_error.rb +31 -0
  85. data/lib/leftovers/precompilers/haml.rb +23 -3
  86. data/lib/leftovers/precompilers/json.rb +1 -1
  87. data/lib/leftovers/precompilers/precompiler.rb +3 -3
  88. data/lib/leftovers/precompilers/slim.rb +1 -1
  89. data/lib/leftovers/precompilers/yaml/builder.rb +62 -0
  90. data/lib/leftovers/precompilers/yaml.rb +3 -56
  91. data/lib/leftovers/precompilers.rb +11 -16
  92. data/lib/leftovers/processor_builders/action.rb +15 -19
  93. data/lib/leftovers/processor_builders/add_prefix.rb +4 -6
  94. data/lib/leftovers/processor_builders/add_suffix.rb +4 -6
  95. data/lib/leftovers/processor_builders/argument.rb +10 -15
  96. data/lib/leftovers/processor_builders/dynamic.rb +12 -30
  97. data/lib/leftovers/processor_builders/each.rb +63 -76
  98. data/lib/leftovers/processor_builders/each_for_definition_set.rb +15 -0
  99. data/lib/leftovers/processor_builders/itself.rb +2 -4
  100. data/lib/leftovers/processor_builders/keyword.rb +4 -4
  101. data/lib/leftovers/processor_builders/keyword_argument.rb +4 -4
  102. data/lib/leftovers/processor_builders/receiver.rb +2 -4
  103. data/lib/leftovers/processor_builders/transform.rb +26 -49
  104. data/lib/leftovers/processor_builders/transform_chain.rb +4 -7
  105. data/lib/leftovers/processor_builders/transform_set.rb +6 -7
  106. data/lib/leftovers/processor_builders/value.rb +2 -2
  107. data/lib/leftovers/processor_builders.rb +2 -15
  108. data/lib/leftovers/processors/add_definition_node.rb +2 -2
  109. data/lib/leftovers/processors/camelize.rb +3 -3
  110. data/lib/leftovers/processors/deconstantize.rb +3 -3
  111. data/lib/leftovers/processors/demodulize.rb +3 -3
  112. data/lib/leftovers/processors/each_for_definition_set.rb +2 -2
  113. data/lib/leftovers/processors/eval.rb +1 -1
  114. data/lib/leftovers/processors/parameterize.rb +3 -3
  115. data/lib/leftovers/processors/placeholder.rb +1 -1
  116. data/lib/leftovers/processors/pluralize.rb +3 -3
  117. data/lib/leftovers/processors/set_default_privacy.rb +1 -1
  118. data/lib/leftovers/processors/set_privacy.rb +1 -1
  119. data/lib/leftovers/processors/singularize.rb +3 -3
  120. data/lib/leftovers/processors/titleize.rb +3 -3
  121. data/lib/leftovers/processors/underscore.rb +3 -3
  122. data/lib/leftovers/processors.rb +2 -44
  123. data/lib/leftovers/rake_task.rb +2 -2
  124. data/lib/leftovers/reporter.rb +44 -42
  125. data/lib/leftovers/runner.rb +40 -0
  126. data/lib/leftovers/todo_reporter.rb +96 -94
  127. data/lib/leftovers/unexpected_case.rb +8 -0
  128. data/lib/leftovers/version.rb +1 -1
  129. data/lib/leftovers.rb +23 -108
  130. metadata +15 -18
  131. data/lib/leftovers/matcher_builders/and_not.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99d72b44b74c747074583f8c9254872a175563d0f25135b7798c5e76f42c19ef
4
- data.tar.gz: 6b4bd9219256b8734df956978892da7ffe028e0539367a1f98d46c73912ae79e
3
+ metadata.gz: 7094671fa508c2a3af0cfdc0b64dfc41346c88a16a9203d901628fe40af66a86
4
+ data.tar.gz: 35ae640a73003aaf96a362ca08e3c92b51b46e93184b1c3641a5427a1dce31d4
5
5
  SHA512:
6
- metadata.gz: d51c93c652bdd0aa55a176c1600e9d557fd29e7e9726411d7ac6eb086178a655e17e96e8d7530c97945f169d32961649358dd712daf9e50cb82b30caa1b55c10
7
- data.tar.gz: b8ca04321b17c7d9c9b831f3fb2fab47554d859f910d38f08a04d41f344c4585a1008019af12d13b3e2807027fe6ba7d6fd6a4d1eca3fb947d68d6812249bc39
6
+ metadata.gz: 4da3eb08e61869a3d5a82c8a0ecdfb7217872299cee46d1ec7ac0234c892c10a0afa5ca3786e23939d893302cf83e2d91e4cb33939c02e4f6b856c51aef22cdc
7
+ data.tar.gz: 29f81218dfad69a62ea35032cc4149eff849a363067b67aa9175a568674e473e6a28f2b0eeb5d6de36246917efb911a527163aab45e7382ff0d915a843777b99
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # v0.12.0
2
+ - improve error handling when a file can't be processed
3
+ - fail rather than warn when encountering a syntax error in a file being processed
4
+
5
+ # v0.11.2
6
+
7
+ - add `has_block: true/false` for matching method calls with a block.
8
+ - fix block_pass (`call(&block)`) being considered a regular argument, which meant the keyword arguments was a hash in the second-last position instead of the last position, so weren't keyword arguments, and also inflated how many positional arguments there were.
9
+ - Fixed integration with Haml 6.x
10
+ - Noted the with_options limitation in readme
11
+ - Add more rspec config: `RSpec::Matchers.define`, `matcher {}`, `alias_matcher`
12
+
1
13
  # v0.11.1
2
14
  - Fixed an issue with parsing files that have `MyConstant ||= value` patterns #19 (thanks for the pr - @kamoh)
3
15
 
data/README.md CHANGED
@@ -185,6 +185,7 @@ see the [built in config files](https://github.com/robotdana/leftovers/tree/main
185
185
  Add the method/pattern to the `dynamic:` list with `skip: true` in the `.leftovers.yml`, or add an inline comment with the list of possibilities `# leftovers:call my_method_1, my_method_2`.
186
186
  - Leftovers compares by name only, so multiple definitions with the same name will count as used even if only one is.
187
187
  - haml, slim & erb line and column numbers will be wrong as the files have to be precompiled before checking.
188
+ - dynamic calls & definitions based on values copied by rails `with_options` method aren't captured by leftovers.
188
189
 
189
190
  ## Other tools
190
191
 
@@ -250,6 +250,7 @@ Each entry must have at least one of the following properties to restrict which
250
250
  - [`paths:`](#paths)
251
251
  - [`has_arguments:`](#has_arguments)
252
252
  - [`has_receiver:`](#has_receiver)
253
+ - [`has_block:`](#has_block)
253
254
  - [`type:`](#type)
254
255
  - [`privacy:`](#privacy)
255
256
  - [`unless:`](#unless)
@@ -528,6 +529,12 @@ Arrays are not necessary for single values and if the rule contains only `at:` i
528
529
 
529
530
  Positional arguments are zero indexed
530
531
 
532
+ ## `has_block:`
533
+
534
+ Use `has_block: true` or `has_block: false` filter by whether they have a block or not
535
+
536
+ This will match either `this { syntax }` or `this(&syntax)`
537
+
531
538
  ## `keywords:`
532
539
  When the keyword argument **keywords** are the thing being called.
533
540
 
data/exe/leftovers CHANGED
@@ -3,4 +3,6 @@
3
3
 
4
4
  require_relative '../lib/leftovers'
5
5
 
6
- exit Leftovers::CLI.new(argv: ARGV).run
6
+ Leftovers.stderr = $stderr
7
+ Leftovers.stdout = $stdout
8
+ exit ::Leftovers::CLI.new(argv: ::ARGV).run
data/leftovers.gemspec CHANGED
@@ -4,9 +4,9 @@ lib = ::File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'leftovers/version'
6
6
 
7
- Gem::Specification.new do |spec|
7
+ ::Gem::Specification.new do |spec|
8
8
  spec.name = 'leftovers'
9
- spec.version = Leftovers::VERSION
9
+ spec.version = ::Leftovers::VERSION
10
10
  spec.authors = ['Dana Sherson']
11
11
  spec.email = ['robot@dana.sh']
12
12
 
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.metadata['rubygems_mfa_required'] = 'true'
22
22
  spec.required_ruby_version = '>= 2.5.0'
23
23
 
24
- spec.files = Dir.glob('{lib,exe,docs}/**/{*,.*}') + %w{
24
+ spec.files = ::Dir.glob('{lib,exe,docs}/**/{*,.*}') + %w{
25
25
  CHANGELOG.md
26
26
  Gemfile
27
27
  LICENSE.txt
@@ -35,7 +35,6 @@ Gem::Specification.new do |spec|
35
35
  spec.add_development_dependency 'activesupport'
36
36
  spec.add_development_dependency 'benchmark-ips'
37
37
  spec.add_development_dependency 'bundler', '~> 2.0'
38
- spec.add_development_dependency 'did_you_mean'
39
38
  spec.add_development_dependency 'haml'
40
39
  spec.add_development_dependency 'pry', '~> 0.1'
41
40
  spec.add_development_dependency 'rake', '>= 13'
@@ -156,7 +156,7 @@ dynamic:
156
156
  calls: 1
157
157
  unless:
158
158
  - has_argument: 2
159
- # - has_block_argument: true
159
+ - has_block: true
160
160
 
161
161
  # https://api.rubyonrails.org/classes/ActiveSupport/Callbacks/ClassMethods.html#method-i-skip_callback
162
162
  - name: skip_callback
data/lib/config/rspec.yml CHANGED
@@ -62,3 +62,24 @@ dynamic:
62
62
  has_argument: 1
63
63
  defines: 0
64
64
  path: /spec/
65
+
66
+ - name: define
67
+ has_receiver:
68
+ match: Matchers
69
+ has_receiver: RSpec
70
+ defines:
71
+ argument: 0
72
+ path: /spec/
73
+
74
+ - name: matcher
75
+ has_block: true
76
+ defines:
77
+ argument: 0
78
+ path: /spec/
79
+
80
+ - name: alias_matcher
81
+ defines:
82
+ argument: 0
83
+ calls:
84
+ argument: 1
85
+ path: /spec/
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class ArrayNode < ::Leftovers::AST::Node
6
- include Leftovers::AST::HasArguments
5
+ class ArrayNode < Node
6
+ include HasArguments
7
7
 
8
8
  alias_method :arguments, :children
9
9
  alias_method :as_arguments_list, :arguments
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class BlockNode < ::Leftovers::AST::Node
5
+ class BlockNode < Node
6
6
  def proc?
7
7
  name = first.name
8
8
  name == :lambda || name == :proc
@@ -11,28 +11,29 @@ module Leftovers
11
11
 
12
12
  def self.node_class(type) # rubocop:disable Metrics
13
13
  case type
14
- when :array then ::Leftovers::AST::ArrayNode
15
- when :block then ::Leftovers::AST::BlockNode
16
- when :casgn then ::Leftovers::AST::CasgnNode
17
- when :const then ::Leftovers::AST::ConstNode
18
- when :def then ::Leftovers::AST::DefNode
19
- when :defs then ::Leftovers::AST::DefsNode
20
- when :false then ::Leftovers::AST::FalseNode
21
- when :hash then ::Leftovers::AST::HashNode
22
- when :int, :float then ::Leftovers::AST::NumericNode
23
- when :lvar, :ivar, :gvar, :cvar then ::Leftovers::AST::VarNode
24
- when :ivasgn, :cvasgn, :gvasgn then ::Leftovers::AST::VasgnNode
25
- when :module, :class then ::Leftovers::AST::ModuleNode
26
- when :nil then ::Leftovers::AST::NilNode
27
- when :send, :csend then ::Leftovers::AST::SendNode
28
- when :str then ::Leftovers::AST::StrNode
29
- when :sym then ::Leftovers::AST::SymNode
30
- when :true then ::Leftovers::AST::TrueNode
31
- else ::Leftovers::AST::Node
14
+ when :array then ArrayNode
15
+ when :block then BlockNode
16
+ when :casgn then CasgnNode
17
+ when :const then ConstNode
18
+ when :def then DefNode
19
+ when :defs then DefsNode
20
+ when :false then FalseNode
21
+ when :hash then HashNode
22
+ when :int, :float then NumericNode
23
+ when :lvar, :ivar, :gvar, :cvar then VarNode
24
+ when :ivasgn, :cvasgn, :gvasgn then VasgnNode
25
+ when :module, :class then ModuleNode
26
+ when :nil then NilNode
27
+ when :send, :csend then SendNode
28
+ when :str then StrNode
29
+ when :sym then SymNode
30
+ when :true then TrueNode
31
+ else Node
32
32
  end
33
33
  end
34
34
 
35
35
  # Don't complain about invalid strings
36
+ # This is called by ::Parser::AST internals
36
37
  def string_value(token) # leftovers:keep
37
38
  value(token)
38
39
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class CasgnNode < ::Leftovers::AST::Node
6
- include Leftovers::AST::HasArguments
5
+ class CasgnNode < Node
6
+ include HasArguments
7
7
 
8
8
  alias_method :name, :second
9
9
  alias_method :to_sym, :second
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class ConstNode < ::Leftovers::AST::Node
5
+ class ConstNode < Node
6
6
  alias_method :receiver, :first
7
7
  alias_method :name, :second
8
8
  alias_method :to_sym, :second
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class DefNode < ::Leftovers::AST::Node
5
+ class DefNode < Node
6
6
  alias_method :name, :first
7
7
  alias_method :to_sym, :first
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class DefsNode < ::Leftovers::AST::Node
5
+ class DefsNode < Node
6
6
  alias_method :name, :second
7
7
  alias_method :to_sym, :second
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class FalseNode < ::Leftovers::AST::Node
5
+ class FalseNode < Node
6
6
  def to_scalar_value
7
7
  false
8
8
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class HashNode < ::Leftovers::AST::Node
6
- include Leftovers::AST::HasArguments
5
+ class HashNode < Node
6
+ include HasArguments
7
7
 
8
8
  def arguments
9
9
  @memo[:arguments] ||= [self]
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class ModuleNode < ::Leftovers::AST::Node
5
+ class ModuleNode < Node
6
6
  def name
7
7
  first.name
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class NilNode < ::Leftovers::AST::Node
5
+ class NilNode < Node
6
6
  def to_scalar_value
7
7
  nil
8
8
  end
@@ -17,7 +17,7 @@ module Leftovers
17
17
  def updated(type = nil, children = nil, properties = nil) # leftovers:keep
18
18
  maybe_copy = super
19
19
 
20
- class_for_type = Leftovers::AST::Builder.node_class(maybe_copy.type)
20
+ class_for_type = Builder.node_class(maybe_copy.type)
21
21
  return maybe_copy if maybe_copy.instance_of?(class_for_type)
22
22
 
23
23
  class_for_type.new(maybe_copy.type, maybe_copy.children, location: maybe_copy.loc)
@@ -43,6 +43,14 @@ module Leftovers
43
43
  @memo[:privacy] || :public
44
44
  end
45
45
 
46
+ def parent
47
+ @memo[:parent]
48
+ end
49
+
50
+ def parent=(value)
51
+ @memo[:parent] = value
52
+ end
53
+
46
54
  def to_scalar_value
47
55
  nil
48
56
  end
@@ -98,6 +106,10 @@ module Leftovers
98
106
  def name
99
107
  nil
100
108
  end
109
+
110
+ def block_given?
111
+ false
112
+ end
101
113
  end
102
114
  end
103
115
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class NumericNode < ::Leftovers::AST::Node
5
+ class NumericNode < Node
6
6
  alias_method :to_scalar_value, :first
7
7
 
8
8
  def scalar?
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class SendNode < ::Leftovers::AST::Node
6
- include Leftovers::AST::HasArguments
5
+ class SendNode < Node
6
+ include HasArguments
7
7
 
8
8
  alias_method :receiver, :first
9
9
  alias_method :name, :second
@@ -14,12 +14,25 @@ module Leftovers
14
14
  end
15
15
 
16
16
  def arguments
17
- @memo[:arguments] ||= children.drop(2)
17
+ @memo[:arguments] ||= if block_pass_argument?
18
+ children[2...-1]
19
+ else
20
+ children.drop(2)
21
+ end
18
22
  end
19
23
 
20
24
  def as_arguments_list
21
25
  first.as_arguments_list if name == :freeze
22
26
  end
27
+
28
+ def block_pass_argument?
29
+ last_child = children.last
30
+ last_child.respond_to?(:type) && last_child.type == :block_pass
31
+ end
32
+
33
+ def block_given?
34
+ block_pass_argument? || parent&.type == :block
35
+ end
23
36
  end
24
37
  end
25
38
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class StrNode < ::Leftovers::AST::Node
5
+ class StrNode < Node
6
6
  alias_method :to_scalar_value, :first
7
7
 
8
8
  def name
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class SymNode < ::Leftovers::AST::Node
5
+ class SymNode < Node
6
6
  alias_method :name, :first
7
7
  alias_method :to_scalar_value, :first
8
8
  alias_method :to_sym, :first
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class TrueNode < ::Leftovers::AST::Node
5
+ class TrueNode < Node
6
6
  def to_scalar_value
7
7
  true
8
8
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class VarNode < ::Leftovers::AST::Node
5
+ class VarNode < Node
6
6
  alias_method :name, :first
7
7
  alias_method :to_sym, :first
8
8
 
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- class VasgnNode < ::Leftovers::AST::Node
6
- include Leftovers::AST::HasArguments
5
+ class VasgnNode < Node
6
+ include HasArguments
7
7
 
8
8
  alias_method :name, :first
9
9
  alias_method :to_sym, :first
data/lib/leftovers/ast.rb CHANGED
@@ -1,26 +1,7 @@
1
- # frozen-string-literal: true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
4
  module AST
5
- autoload(:ArrayNode, "#{__dir__}/ast/array_node")
6
- autoload(:BlockNode, "#{__dir__}/ast/block_node")
7
- autoload(:Builder, "#{__dir__}/ast/builder")
8
- autoload(:CasgnNode, "#{__dir__}/ast/casgn_node")
9
- autoload(:ConstNode, "#{__dir__}/ast/const_node")
10
- autoload(:DefNode, "#{__dir__}/ast/def_node")
11
- autoload(:DefsNode, "#{__dir__}/ast/defs_node")
12
- autoload(:FalseNode, "#{__dir__}/ast/false_node")
13
- autoload(:HashNode, "#{__dir__}/ast/hash_node")
14
- autoload(:HasArguments, "#{__dir__}/ast/has_arguments")
15
- autoload(:ModuleNode, "#{__dir__}/ast/module_node")
16
- autoload(:NilNode, "#{__dir__}/ast/nil_node")
17
- autoload(:Node, "#{__dir__}/ast/node")
18
- autoload(:NumericNode, "#{__dir__}/ast/numeric_node")
19
- autoload(:SendNode, "#{__dir__}/ast/send_node")
20
- autoload(:StrNode, "#{__dir__}/ast/str_node")
21
- autoload(:SymNode, "#{__dir__}/ast/sym_node")
22
- autoload(:TrueNode, "#{__dir__}/ast/true_node")
23
- autoload(:VasgnNode, "#{__dir__}/ast/vasgn_node")
24
- autoload(:VarNode, "#{__dir__}/ast/var_node")
5
+ include Autoloader
25
6
  end
26
7
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ # zero dependency zeitwerk
5
+ module Autoloader
6
+ ALL_CAPS_NAMES = %w{ast cli version erb json yaml}.freeze
7
+
8
+ def self.included(klass)
9
+ ::Dir[glob_children(klass)].each_entry do |path|
10
+ klass.autoload(class_from_path(path), path)
11
+ end
12
+ end
13
+
14
+ def self.class_from_path(path)
15
+ name = ::File.basename(path).delete_suffix('.rb')
16
+ if ALL_CAPS_NAMES.include?(name)
17
+ name.upcase
18
+ else
19
+ name.gsub(/(?:^|_)(\w)/, &:upcase).delete('_')
20
+ end
21
+ end
22
+
23
+ def self.dir_path_from_class(klass)
24
+ klass.name.gsub(/::/, '/')
25
+ .gsub(/(?<=[a-z])([A-Z])/, '_\1').downcase
26
+ end
27
+
28
+ def self.glob_children(klass)
29
+ "#{root}/#{dir_path_from_class(klass)}/*.rb"
30
+ end
31
+
32
+ def self.root
33
+ ::File.dirname(__dir__)
34
+ end
35
+ end
36
+ end
data/lib/leftovers/cli.rb CHANGED
@@ -1,73 +1,92 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'optparse'
4
+
4
5
  module Leftovers
5
6
  class CLI
6
- def initialize(argv: [], stdout: $stdout, stderr: $stderr)
7
+ def initialize(argv: [])
7
8
  @argv = argv
8
- @stdout = stdout
9
- @stderr = stderr
10
9
  end
11
10
 
12
11
  def run
13
- catch(:leftovers_exit) do
14
- Leftovers.reset
15
- parse_options
12
+ parse_options
16
13
 
17
- Leftovers.run(stdout: stdout, stderr: stderr)
18
- end
14
+ runner.run
15
+ rescue ::Leftovers::Error => e
16
+ Leftovers.warn("\e[31m#{e.class}: #{e.message}\e[0m\n\n#{e.backtrace.join("\n")}")
17
+ 1
18
+ rescue ::Leftovers::Exit => e
19
+ e.status # what why?
19
20
  end
20
21
 
21
22
  private
22
23
 
23
- attr_reader :argv, :stdout, :stderr
24
+ attr_reader :argv
24
25
 
25
- def parse_options # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
26
- opts = OptionParser.new
27
- Leftovers.parallel = true
28
- Leftovers.progress = true
26
+ def option_parser
27
+ @option_parser ||= ::OptionParser.new do |o|
28
+ o.banner = 'Usage: leftovers [options]'
29
29
 
30
- opts.banner = 'Usage: leftovers [options]'
31
-
32
- opts.on('--[no-]parallel', 'Run in parallel or not, default --parallel') do |p|
33
- Leftovers.parallel = p
30
+ o.on('--[no-]parallel', 'Run in parallel or not, default --parallel') { |p| parallel(p) }
31
+ o.on('--[no-]progress', 'Show live counts or not, default --progress') { |p| progress(p) }
32
+ o.on('--dry-run', 'Print a list of files that would be looked at') { dry_run }
33
+ o.on('--view-compiled', 'Print the compiled content of the files') { view_compiled }
34
+ o.on('--write-todo', 'Create a config file with the existing unused items') { write_todo }
35
+ o.on('-v', '--version', 'Print the current version') { print_version }
36
+ o.on('-h', '--help', 'Print this message') { print_help }
34
37
  end
38
+ end
35
39
 
36
- opts.on('--[no-]progress', 'Show progress counts or not, default --progress') do |p|
37
- Leftovers.progress = p
38
- end
40
+ def parse_options
41
+ option_parser.parse!(argv)
42
+ rescue ::OptionParser::ParseError => e
43
+ ::Leftovers.error("CLI Error: #{e.message}", option_parser.help)
44
+ end
39
45
 
40
- opts.on('--dry-run', 'Output files that will be looked at') do
41
- Leftovers::FileList.new.each { |f| stdout.puts f.relative_path }
42
- Leftovers.exit
43
- end
46
+ def runner
47
+ @runner ||= Runner.new
48
+ end
44
49
 
45
- opts.on('--view-compiled', 'Output the compiled content of the files') do
46
- Leftovers::FileList.new(argv_rules: argv)
47
- .each { |f| stdout.puts "\e[0;2m#{f.relative_path}\e[0m\n#{f.ruby}" }
48
- Leftovers.exit
49
- end
50
+ def exit(status = 0)
51
+ ::Leftovers.exit status
52
+ end
50
53
 
51
- opts.on('--write-todo', 'Outputs the unused items in a todo file to gradually fix') do
52
- Leftovers.reporter = Leftovers::TodoReporter.new
53
- end
54
+ def dry_run
55
+ FileList.new.each { |file| ::Leftovers.puts file.relative_path }
54
56
 
55
- opts.on('-v', '--version', 'Returns the current version') do
56
- stdout.puts(Leftovers::VERSION)
57
- Leftovers.exit
58
- end
57
+ exit
58
+ end
59
59
 
60
- opts.on('-h', '--help', 'Shows this message') do
61
- stdout.puts(opts.help)
62
- Leftovers.exit
60
+ def view_compiled
61
+ FileList.new(argv_rules: argv).each do |file|
62
+ ::Leftovers.puts "\e[0;2m#{file.relative_path}\e[0m\n#{file.ruby}"
63
63
  end
64
64
 
65
- opts.parse!(argv)
66
- rescue OptionParser::InvalidOption => e
67
- stderr.puts("\e[31mCLI Error: #{e.message}\e[0m")
68
- stderr.puts ''
69
- stderr.puts(opts.help)
70
- Leftovers.exit 1
65
+ exit
66
+ end
67
+
68
+ def print_version
69
+ ::Leftovers.puts(VERSION)
70
+
71
+ exit
72
+ end
73
+
74
+ def print_help
75
+ ::Leftovers.puts(option_parser.help)
76
+
77
+ exit
78
+ end
79
+
80
+ def parallel(value)
81
+ runner.parallel = value
82
+ end
83
+
84
+ def progress(value)
85
+ runner.progress = value
86
+ end
87
+
88
+ def write_todo
89
+ runner.reporter = TodoReporter
71
90
  end
72
91
  end
73
92
  end