degem 0.1.0 → 0.3.0

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: 99c4e8766d6d3f8e6f710e2e13c0e0007190617fff3f83d198b469f0aec2ffb9
4
- data.tar.gz: 4df2c08f44fc1eb1c694a85ae55d36421f4610bb717f3789eb8b5feb93c726e3
3
+ metadata.gz: 683ca7f47acea423692062935b4ccd5285e5aa764a12883a4f34237af7be248a
4
+ data.tar.gz: 1a9a8e898b9f4afcd1668b65a0ebc2b7928a84efa6c31e263c237114fa0a2069
5
5
  SHA512:
6
- metadata.gz: 26145f7a46f9b9a3152092ba4fa7065261630b66c5edf443d7e90d1eff1c88264814edefc3048d73c39b24cb7a7e9709114baf5959133de351b841967f17fba0
7
- data.tar.gz: 5f3d721a7bf24c8541f93d5a67672ca71f8bfa7550a11822af4e214d6e338d905b9a4f8a3324457593de276c88cbb18eaf10af910faa8470a9abca9096787eca
6
+ metadata.gz: b8e874de8d90b2a2e833b1685938ce9302426c3af5acf8e60bcf26cb0dab994a1520173269a366969018e69fb1abba74f1c4900235a0f7051739073a3962f70d
7
+ data.tar.gz: 6c19cd8a7e75ef66396e4dc209a14b77765e323804952769cd30a0d9267abb15bf9388ab58ee3f22002320585bb211f80d9d0e86163c7ac0a6b50e992b046cb6
data/lib/degem/cli.rb CHANGED
@@ -9,33 +9,29 @@ module Degem
9
9
  end
10
10
 
11
11
  def initialize(stderr)
12
- @stderr = stderr
12
+ Degem.stderr = stderr
13
13
  end
14
14
 
15
15
  def call
16
16
  unless gemfile_exists?
17
- @stderr.puts "Gemfile not found in the current directory"
17
+ Degem.stderr.puts "Gemfile not found in the current directory"
18
18
  return 1
19
19
  end
20
20
 
21
21
  unused = find_unused.call
22
22
  decorated = decorate_rubygems.call(unused)
23
- Report.new(@stderr).call(decorated)
23
+ Report.new.call(decorated)
24
24
  0
25
25
  end
26
26
 
27
27
  private
28
28
 
29
29
  def find_unused
30
- FindUnused.new(
31
- gemfile_path: GEMFILE,
32
- gem_specification: Gem::Specification,
33
- grep: Grep.new(@stderr)
34
- )
30
+ FindUnused.new(gemfile_path: GEMFILE)
35
31
  end
36
32
 
37
33
  def decorate_rubygems
38
- DecorateRubygems.new(
34
+ DecorateUnusedGems.new(
39
35
  gem_specification: Gem::Specification,
40
36
  git_adapter: GitAdapter.new
41
37
  )
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Degem
4
- class DecorateRubygems
4
+ class DecorateUnusedGems
5
5
  def initialize(gem_specification:, git_adapter:)
6
6
  @gem_specification = gem_specification
7
7
  @git_adapter = git_adapter
@@ -11,7 +11,7 @@ module Degem
11
11
  rubygems.map do |rubygem|
12
12
  gemspec = @gem_specification.find_by_name(rubygem.name)
13
13
  git = @git_adapter.call(rubygem.name)
14
- Rubygem.new(rubygem, gemspec, git)
14
+ UnusedGem.new(rubygem, gemspec, git)
15
15
  end
16
16
  end
17
17
  end
@@ -2,16 +2,16 @@
2
2
 
3
3
  module Degem
4
4
  class FindUnused
5
- def initialize(gemfile_path:, gem_specification:, grep: Grep.new, bundle_paths: GitLsFiles.new)
5
+ def initialize(gemfile_path:, gem_specification: Gem::Specification, bundle_paths: GitLsFiles.new)
6
6
  @gemfile_path = gemfile_path
7
7
  @gem_specification = gem_specification
8
- @grep = grep
9
- @bundle_paths = bundle_paths.call(File.dirname(gemfile_path))
8
+ fallback = Dir.glob(File.join(File.dirname(gemfile_path), "**/*.rb"))
9
+ @bundle_paths = bundle_paths.call(fallback)
10
10
  end
11
11
 
12
12
  def call
13
13
  rubygems = gemfile.rubygems.reject { _1.name == "degem" }
14
- rubygems = reject_railties(rubygems) if rails?
14
+ rubygems = reject_railties(rubygems) if gemfile.rails?
15
15
  reject_used(rubygems)
16
16
  end
17
17
 
@@ -20,162 +20,36 @@ module Degem
20
20
  attr_reader :gemfile_path
21
21
 
22
22
  def reject_railties(rubygems)
23
- rubygems
24
- .reject { _1.name == "rails" }
25
- .reject do |rubygem|
26
- gem_path = @gem_specification.find_by_name(rubygem.name).full_gem_path
27
- @grep.match?(/(Rails::Railtie|Rails::Engine)/, gem_path)
28
- end
23
+ rubygems.reject(&:rails?).reject(&:railtie?)
29
24
  end
30
25
 
31
26
  def reject_used(rubygems)
32
- candidates = rubygems.map { Matcher.new(rubygem: _1, matchers: matchers) }
33
- @grep.inverse_many(candidates, @bundle_paths).map(&:rubygem)
34
- end
35
-
36
- def matchers
37
- [
38
- method(:based_on_top_module),
39
- method(:based_on_top_composite_module_dash),
40
- method(:based_on_top_composite_module_underscore),
41
- method(:based_on_top_call),
42
- method(:based_on_top_composite_call_dash),
43
- method(:based_on_top_composite_call_underscore),
44
- method(:based_on_require),
45
- method(:based_on_require_prefix_path),
46
- method(:based_on_require_path)
47
- ].compact
48
- end
49
-
50
- def gemfile
51
- @gemfile ||= ParseGemfile.new.call(gemfile_path)
52
- end
53
-
54
- def rails?
55
- @rails ||= gemfile.rails?
56
- end
57
-
58
- # gem foo -> Foo:: (but not XFoo:: or X::Foo)
59
- def based_on_top_module(rubygem, line)
60
- return false if rubygem.name.include?("-")
61
-
62
- regex = %r{
63
- (?<!\w::) # Do not match if :: before
64
- (?<!\w) # Do not match if \w before
65
- #{rubygem.name.capitalize}
66
- ::
67
- }x
68
- regex.match?(line)
69
- end
70
-
71
- # gem foo_bar -> FooBar (but not XFooBar or X::FooBar)
72
- def based_on_top_composite_module_underscore(rubygem, line)
73
- return false unless rubygem.name.include?("_")
74
-
75
- regex = %r{
76
- (?<!\w::) # Do not match if :: before
77
- (?<!\w) # Do not match if \w before
78
- #{rubygem.name.split("_").map(&:capitalize).join}
79
- ::
80
- }x
81
- regex.match?(line)
82
- end
83
-
84
- # gem foo-bar -> Foo::Bar (but not XFoo::Bar or X::Foo::Bar)
85
- def based_on_top_composite_module_dash(rubygem, line)
86
- return false unless rubygem.name.include?("-")
87
-
88
- regex = %r{
89
- (?<!\w::) # Do not match if :: before
90
- (?<!\w) # Do not match if \w before
91
- #{rubygem.name.split("-").map(&:capitalize).join("::")}
92
- }x
93
- regex.match?(line)
94
- end
95
-
96
- # gem foo -> Foo. (but not X::Foo. or XBar.)
97
- def based_on_top_call(rubygem, line)
98
- return false if rubygem.name.include?("-")
99
-
100
- regex = %r{
101
- (?<!\w::) # Do not match if :: before
102
- (?<!\w) # Do not match if \w before
103
- #{rubygem.name.capitalize}
104
- \.
105
- }x
106
- regex.match?(line)
107
- end
108
-
109
- # gem foo-bar -> FooBar. (but not X::FooBar. or XFooBar.)
110
- def based_on_top_composite_call_dash(rubygem, line)
111
- return false unless rubygem.name.include?("-")
112
-
113
- regex = %r{
114
- (?<!\w::) # Do not match if :: before
115
- (?<!\w) # Do not match if \w before
116
- #{rubygem.name.split("-").map(&:capitalize).join}
117
- \.
118
- }x
119
- regex.match?(line)
27
+ bundle = ParseRuby.new.call(@bundle_paths)
28
+ rubygems = reject_required(rubygems, bundle.requires)
29
+ reject_consts(rubygems, bundle.consts)
120
30
  end
121
31
 
122
- # gem foo_bar -> FooBar. (but not X::FooBar. or XFooBar.)
123
- def based_on_top_composite_call_underscore(rubygem, line)
124
- return false unless rubygem.name.include?("_")
125
-
126
- regex = %r{
127
- (?<!\w::) # Do not match if :: before
128
- (?<!\w) # Do not match if \w before
129
- #{rubygem.name.split("_").map(&:capitalize).join}
130
- \.
131
- }x
132
- regex.match?(line)
133
- end
134
-
135
- # gem foo-bar -> require 'foo-bar'
136
- def based_on_require(rubygem, line)
137
- regex = %r{
138
- ^
139
- \s*
140
- require
141
- \s+
142
- ['"]
143
- #{rubygem.name}
144
- ['"]
145
- }x
146
- regex.match?(line)
32
+ def reject_consts(rubygems, bundle_consts)
33
+ rubygems.reject do |rubygem|
34
+ rubygem.own_consts.any? do |own_const|
35
+ bundle_consts.include?(own_const)
36
+ end
37
+ end
147
38
  end
148
39
 
149
- # gem foo-bar -> require 'foo/bar'
150
- def based_on_require_path(rubygem, line)
151
- return false unless rubygem.name.include?("-")
40
+ def reject_required(rubygems, bundle_requires)
41
+ rubygems.reject do |rubygem|
42
+ bundle_requires.any? do |bundle_require|
43
+ next true if bundle_require == rubygem.name
44
+ next true if bundle_require == rubygem.name.tr("-", "/")
152
45
 
153
- regex = %r{
154
- ^
155
- \s*
156
- require
157
- \s+
158
- ['"]
159
- #{rubygem.name.tr("-", "/")} # match foo/bar when rubygem is foo-bar
160
- ['"]
161
- }x
162
- regex.match?(line)
46
+ bundle_require.start_with?("#{rubygem.name}/")
47
+ end
48
+ end
163
49
  end
164
50
 
165
- # gem foo -> require 'foo/'
166
- def based_on_require_prefix_path(rubygem, line)
167
- return false if rubygem.name.include?("-")
168
-
169
- regex = %r{
170
- ^
171
- \s*
172
- require
173
- \s+
174
- ['"]
175
- #{rubygem.name}
176
- /
177
- }x
178
- regex.match?(line)
51
+ def gemfile
52
+ @gemfile ||= ParseGemfile.new(@gem_specification).call(gemfile_path)
179
53
  end
180
54
  end
181
55
  end
data/lib/degem/gemfile.rb CHANGED
@@ -2,22 +2,28 @@
2
2
 
3
3
  module Degem
4
4
  class Gemfile
5
- def initialize(dsl)
5
+ def initialize(dsl:, gem_specification:)
6
6
  @dsl = dsl
7
+ @gem_specification = gem_specification
7
8
  end
8
9
 
9
10
  def rubygems
10
- @rubygems ||= (gemfile_dependencies + gemspec_dependencies).uniq
11
+ @rubygems ||=
12
+ (gemfile_dependencies + gemspec_dependencies)
13
+ .map { Rubygem.new(rubygem: _1, gem_specification: @gem_specification) }
14
+ .uniq
11
15
  end
12
16
 
13
17
  def rails?
14
- @rails ||= rubygems.map(&:name).include?("rails")
18
+ !!rubygems.find(&:rails?)
15
19
  end
16
20
 
17
21
  private
18
22
 
19
23
  def gemfile_dependencies
20
- @dsl.dependencies.select(&:should_include?)
24
+ @dsl.dependencies.select(&:should_include?).reject do |dependency|
25
+ @dsl.gemspecs.flat_map(&:name).include?(dependency.name)
26
+ end
21
27
  end
22
28
 
23
29
  def gemspec_dependencies
@@ -2,10 +2,14 @@
2
2
 
3
3
  module Degem
4
4
  class ParseGemfile
5
+ def initialize(gem_specification = Gem::Specification)
6
+ @gem_specification = gem_specification
7
+ end
8
+
5
9
  def call(gemfile_path)
6
10
  dsl = Bundler::Dsl.new
7
11
  dsl.eval_gemfile(gemfile_path)
8
- Gemfile.new(dsl)
12
+ Gemfile.new(dsl: dsl, gem_specification: @gem_specification)
9
13
  end
10
14
 
11
15
  private
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Degem
4
+ class ParseRuby
5
+ def initialize(visitor = Visitor)
6
+ @visitor = visitor
7
+ end
8
+
9
+ def call(path)
10
+ visitor = @visitor.new
11
+ Array(path).each do |path|
12
+ visitor.path = path
13
+ Prism.parse_file(path).value.accept(visitor)
14
+ Degem.stderr.putc "."
15
+ end
16
+ visitor
17
+ end
18
+ end
19
+
20
+ require "prism"
21
+
22
+ class Visitor < Prism::Visitor
23
+ def initialize
24
+ @requires = Set.new
25
+ @paths = Set.new
26
+ @classes = Set.new
27
+ @modules = Set.new
28
+ @path = nil
29
+ @stack = []
30
+ super
31
+ end
32
+
33
+ def requires = @requires.to_a
34
+ def consts = (@paths.union(@classes).union(@modules)).to_a
35
+ def paths = @paths.to_a
36
+ def classes = @classes.to_a
37
+ def modules = @modules.to_a
38
+ attr_writer :path
39
+
40
+ def visit_call_node(node)
41
+ visit_require_call_node(node)
42
+ super
43
+ end
44
+
45
+ def visit_module_node(node)
46
+ @stack.push(node)
47
+ super
48
+ @modules.add(@stack.map(&:name).join("::"))
49
+ @stack.pop
50
+ end
51
+
52
+ def visit_class_node(node)
53
+ @stack.push(node)
54
+ super
55
+ @stack.pop
56
+ *modules, klass = node.constant_path.full_name_parts rescue [[], node.name]
57
+ @modules.add((@stack.map(&:name) + modules).join("::")) if modules.any?
58
+ @classes.add((@stack.map(&:name) + modules + [klass]).join("::"))
59
+ end
60
+
61
+ def visit_constant_path_node(node)
62
+ paths_from(node).each { @paths.add(_1) }
63
+ super
64
+ end
65
+
66
+ def visit_constant_read_node(node)
67
+ @paths.add(node.name.to_s) unless @stack.find { _1.constant_path == node }
68
+ super
69
+ end
70
+
71
+ private
72
+
73
+ def visit_require_call_node(node)
74
+ return if node.name.to_s != "require"
75
+ return if node.receiver
76
+ return unless node.arguments
77
+ return unless node.arguments.arguments[0].is_a?(Prism::StringNode)
78
+
79
+ required = node.arguments.arguments[0].unescaped
80
+ @requires.add(required)
81
+ end
82
+
83
+ def from_ancestor_to(node)
84
+ acc = [node]
85
+ node = node.respond_to?(:parent) && node.parent
86
+ while node
87
+ acc.prepend(node)
88
+ node = node.respond_to?(:parent) && node.parent
89
+ end
90
+ acc
91
+ end
92
+
93
+ def paths_from(node)
94
+ from_ancestor_to(node)
95
+ .filter_map { _1.respond_to?(:name) ? _1.name.to_s : nil }
96
+ .tap { _1.singleton_class.include(Scan) }
97
+ .scan { |a, b| [a, b].join("::") }
98
+ end
99
+ end
100
+
101
+ module Scan
102
+ def scan(init = nil)
103
+ if init.nil?
104
+ init = self[0]
105
+ xs = self[1..] || []
106
+ else
107
+ xs = self
108
+ end
109
+
110
+ return self if xs.empty?
111
+
112
+ xs.reduce([init]) do |acc, x|
113
+ acc + [yield(acc.last, x)]
114
+ end
115
+ end
116
+ end
117
+ end
data/lib/degem/report.rb CHANGED
@@ -2,21 +2,17 @@
2
2
 
3
3
  module Degem
4
4
  class Report
5
- def initialize(stderr)
6
- @stderr = stderr
7
- end
8
-
9
5
  def call(rubygems)
10
- @stderr.puts
11
- @stderr.puts
12
- @stderr.puts "The following gems may be unused:"
13
- @stderr.puts
6
+ Degem.stderr.puts
7
+ Degem.stderr.puts
8
+ Degem.stderr.puts "The following gems may be unused (#{rubygems.size}):"
9
+ Degem.stderr.puts
14
10
 
15
11
  rubygems.each do |rubygem|
16
12
  gem_name(rubygem)
17
- @stderr.puts
13
+ Degem.stderr.puts
18
14
  commits(rubygem)
19
- @stderr.puts
15
+ Degem.stderr.puts
20
16
  end
21
17
  end
22
18
 
@@ -30,15 +26,15 @@ module Degem
30
26
  "#{rubygem.name}: #{rubygem.source_code_uri}"
31
27
  end
32
28
 
33
- @stderr.puts(heading)
34
- @stderr.puts("=" * heading.size)
29
+ Degem.stderr.puts(heading)
30
+ Degem.stderr.puts("=" * heading.size)
35
31
  end
36
32
 
37
33
  def commits(rubygem)
38
34
  rubygem.commits.each.with_index do |commit, i|
39
- @stderr.puts("#{commit.hash[0..6]} (#{commit.date}) #{commit.title}")
40
- @stderr.puts(commit.url)
41
- @stderr.puts if i + 1 == rubygem.commits.size
35
+ Degem.stderr.puts("#{commit.hash[0..6]} (#{commit.date}) #{commit.title}")
36
+ Degem.stderr.puts(commit.url)
37
+ Degem.stderr.puts if i + 1 == rubygem.commits.size
42
38
  end
43
39
  end
44
40
  end
data/lib/degem/rubygem.rb CHANGED
@@ -1,16 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "delegate"
4
+
3
5
  module Degem
4
- class Rubygem < MultiDelegator
5
- attr_reader :commits
6
+ class Rubygem < SimpleDelegator
7
+ def initialize(rubygem:, gem_specification:)
8
+ @gem_specification = gem_specification
9
+ super(rubygem)
10
+ end
11
+
12
+ def rails?
13
+ name == "rails"
14
+ end
6
15
 
7
- def initialize(_, _, commits)
8
- super
9
- @commits = commits
16
+ def railtie?
17
+ parsed.consts.grep(/Rails::Railtie|Rails::Engine/).any?
10
18
  end
11
19
 
12
- def source_code_uri
13
- metadata["source_code_uri"] || homepage
20
+ def own_consts
21
+ variations = [
22
+ name,
23
+ name.delete("_-"),
24
+ name.gsub("_", "::"),
25
+ name.gsub("-", "::"),
26
+ *name.split("_").each_cons(2).to_a.map { _1.join("::") },
27
+ *name.split("_").each_cons(2).to_a.map(&:join),
28
+ *name.split("-").each_cons(2).to_a.map { _1.join("::") },
29
+ *name.split("-").each_cons(2).to_a.map(&:join)
30
+ ]
31
+
32
+ parsed.classes + (parsed.modules + parsed.paths).filter do |const|
33
+ variations.any? { |variation| const.downcase == variation.downcase }
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def parsed
40
+ @parsed ||=
41
+ begin
42
+ gem_path = @gem_specification.find_by_name(name).full_gem_path
43
+ paths = Dir.glob(File.join(gem_path, "**", "lib", "**/*.rb"))
44
+ ParseRuby.new.call(paths)
45
+ end
14
46
  end
15
47
  end
16
48
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Degem
4
- class Rubygem < MultiDelegator
4
+ class UnusedGem < MultiDelegator
5
5
  attr_reader :commits
6
6
 
7
7
  def initialize(_, _, commits)
data/lib/degem/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Degem
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/degem.rb CHANGED
@@ -2,18 +2,25 @@
2
2
 
3
3
  require_relative "degem/version"
4
4
  require_relative "degem/gemfile"
5
+ require_relative "degem/rubygem"
5
6
  require_relative "degem/parse_gemfile"
6
- require_relative "degem/grep"
7
7
  require_relative "degem/git_ls_files"
8
- require_relative "degem/matcher"
8
+ require_relative "degem/parse_ruby"
9
9
  require_relative "degem/find_unused"
10
10
  require_relative "degem/multi_delegator"
11
- require_relative "degem/rubygem"
12
- require_relative "degem/decorate_rubygems"
11
+ require_relative "degem/unused_gem"
12
+ require_relative "degem/decorate_unused_gems"
13
13
  require_relative "degem/commit"
14
14
  require_relative "degem/git_adapter"
15
15
  require_relative "degem/report"
16
16
  require_relative "degem/cli"
17
17
 
18
18
  module Degem
19
+ class << self
20
+ attr_writer :stderr
21
+
22
+ def stderr
23
+ @stderr ||= $stderr
24
+ end
25
+ end
19
26
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: degem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - 3v0k4
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-12-05 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2024-12-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: prism
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.2'
13
27
  description: Degem finds unused gems in the Ruby bundle (ie, an app with a `Gemfile`
14
28
  or a gem with both a `Gemfile` and a gemspec).
15
29
  email:
@@ -23,18 +37,17 @@ files:
23
37
  - lib/degem.rb
24
38
  - lib/degem/cli.rb
25
39
  - lib/degem/commit.rb
26
- - lib/degem/decorate_rubygems.rb
27
- - lib/degem/decorated.rb
40
+ - lib/degem/decorate_unused_gems.rb
28
41
  - lib/degem/find_unused.rb
29
42
  - lib/degem/gemfile.rb
30
43
  - lib/degem/git_adapter.rb
31
44
  - lib/degem/git_ls_files.rb
32
- - lib/degem/grep.rb
33
- - lib/degem/matcher.rb
34
45
  - lib/degem/multi_delegator.rb
35
46
  - lib/degem/parse_gemfile.rb
47
+ - lib/degem/parse_ruby.rb
36
48
  - lib/degem/report.rb
37
49
  - lib/degem/rubygem.rb
50
+ - lib/degem/unused_gem.rb
38
51
  - lib/degem/version.rb
39
52
  homepage: https://github.com/3v0k4/degem
40
53
  licenses:
data/lib/degem/grep.rb DELETED
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "find"
4
-
5
- module Degem
6
- class Grep
7
- def initialize(stderr = StringIO.new)
8
- @stderr = stderr
9
- end
10
-
11
- def match?(matcher, dir)
12
- Find.find(File.expand_path(dir)) do |path|
13
- next unless File.file?(path)
14
- next if File.extname(path) != ".rb"
15
-
16
- @stderr.putc "."
17
- File.foreach(path) do |line|
18
- next unless matcher.match?(line)
19
-
20
- return true
21
- end
22
- end
23
-
24
- false
25
- end
26
-
27
- def inverse_many(matchers, paths)
28
- Find.find(*paths) do |path|
29
- next unless File.file?(path)
30
-
31
- @stderr.putc "."
32
- File.foreach(path) do |line|
33
- matchers = matchers.reject do |matcher|
34
- matcher.match?(line)
35
- end
36
- end
37
- end
38
-
39
- matchers
40
- end
41
- end
42
- end
data/lib/degem/matcher.rb DELETED
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Degem
4
- class Matcher
5
- attr_reader :rubygem
6
-
7
- def initialize(rubygem:, matchers:)
8
- @rubygem = rubygem
9
- @matchers = matchers
10
- end
11
-
12
- def match?(string)
13
- @matchers.any? { _1.call(@rubygem, string) }
14
- end
15
- end
16
- end