Skip to content

Commit

Permalink
Do not pass the Deadcode::Definition to plugins on_define_* methods
Browse files Browse the repository at this point in the history
Signed-off-by: Alexandre Terrasa <[email protected]>
  • Loading branch information
Morriar committed Jun 20, 2024
1 parent 9ecd4c3 commit e5fe37c
Show file tree
Hide file tree
Showing 13 changed files with 151 additions and 118 deletions.
3 changes: 2 additions & 1 deletion lib/spoom/cli/deadcode.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ def deadcode(*paths)
next
end

index.finalize!(plugins: plugins)
index.apply_plugins!(plugins)
index.finalize!

if options[:show_defs]
$stderr.puts "\nDefinitions:"
Expand Down
57 changes: 44 additions & 13 deletions lib/spoom/deadcode/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def initialize(model)
@model = model
@definitions = T.let({}, T::Hash[String, T::Array[Definition]])
@references = T.let({}, T::Hash[String, T::Array[Reference]])
@ignored = T.let(Set.new, T::Set[Model::SymbolDef])
end

# Indexing
Expand All @@ -39,11 +40,36 @@ def reference_method(name, location)
(@references[name] ||= []) << Reference.new(name: name, kind: Reference::Kind::Method, location: location)
end

sig { params(symbol_def: Model::SymbolDef).void }
def ignore(symbol_def)
@ignored << symbol_def
end

sig { params(plugins: T::Array[Plugins::Base]).void }
def apply_plugins!(plugins)
@model.symbols.each do |_full_name, symbol|
symbol.definitions.each do |symbol_def|
case symbol_def
when Model::Class
plugins.each { |plugin| plugin.internal_on_define_class(symbol_def) }
when Model::Module
plugins.each { |plugin| plugin.internal_on_define_module(symbol_def) }
when Model::Constant
plugins.each { |plugin| plugin.internal_on_define_constant(symbol_def) }
when Model::Method
plugins.each { |plugin| plugin.internal_on_define_method(symbol_def) }
when Model::Attr
plugins.each { |plugin| plugin.internal_on_define_accessor(symbol_def) }
end
end
end
end

# Mark all definitions having a reference of the same name as `alive`
#
# To be called once all the files have been indexed and all the definitions and references discovered.
sig { params(plugins: T::Array[Plugins::Base]).void }
def finalize!(plugins: [])
sig { void }
def finalize!
@model.symbols.each do |_full_name, symbol|
symbol.definitions.each do |symbol_def|
case symbol_def
Expand All @@ -54,77 +80,82 @@ def finalize!(plugins: [])
full_name: symbol.full_name,
location: symbol_def.location,
)
definition.ignored! if @ignored.include?(symbol_def)
definition.alive! if @references.key?(symbol.name)
define(definition)
plugins.each { |plugin| plugin.internal_on_define_class(symbol_def, definition) }
when Model::Module
definition = Definition.new(
kind: Definition::Kind::Module,
name: symbol.name,
full_name: symbol.full_name,
location: symbol_def.location,
)
definition.ignored! if @ignored.include?(symbol_def)
definition.alive! if @references.key?(symbol.name)
define(definition)
plugins.each { |plugin| plugin.internal_on_define_module(symbol_def, definition) }
when Model::Constant
definition = Definition.new(
kind: Definition::Kind::Constant,
name: symbol.name,
full_name: symbol.full_name,
location: symbol_def.location,
)
definition.ignored! if @ignored.include?(symbol_def)
definition.alive! if @references.key?(symbol.name)
define(definition)
plugins.each { |plugin| plugin.internal_on_define_constant(symbol_def, definition) }
when Model::Method
definition = Definition.new(
kind: Definition::Kind::Method,
name: symbol.name,
full_name: symbol.full_name,
location: symbol_def.location,
)
definition.ignored! if @ignored.include?(symbol_def)
definition.alive! if @references.key?(symbol.name)
define(definition)
plugins.each { |plugin| plugin.internal_on_define_method(symbol_def, definition) }
when Model::AttrAccessor
definition = Definition.new(
kind: Definition::Kind::AttrReader,
name: symbol.name,
full_name: symbol.full_name,
location: symbol_def.location,
)
definition.ignored! if @ignored.include?(symbol_def)
definition.alive! if @references.key?(symbol.name)
define(definition)
plugins.each { |plugin| plugin.internal_on_define_accessor(symbol_def, definition) }

definition = Definition.new(
kind: Definition::Kind::AttrWriter,
name: "#{symbol.name}=",
full_name: "#{symbol.full_name}=",
location: symbol_def.location,
)
definition.ignored! if @ignored.include?(symbol_def)
definition.alive! if @references.key?(symbol.name)
define(definition)
plugins.each { |plugin| plugin.internal_on_define_accessor(symbol_def, definition) }
when Model::AttrReader
definition = Definition.new(
kind: Definition::Kind::AttrReader,
name: symbol.name,
full_name: symbol.full_name,
location: symbol_def.location,
)
definition.ignored! if @ignored.include?(symbol_def)
definition.alive! if @references.key?(symbol.name)
define(definition)
plugins.each { |plugin| plugin.internal_on_define_accessor(symbol_def, definition) }
when Model::AttrWriter
definition = Definition.new(
kind: Definition::Kind::AttrWriter,
name: "#{symbol.name}=",
full_name: "#{symbol.full_name}=",
location: symbol_def.location,
)
definition.ignored! if @ignored.include?(symbol_def)
definition.alive! if @references.key?(symbol.name)
define(definition)
plugins.each { |plugin| plugin.internal_on_define_accessor(symbol_def, definition) }
end
end
end
@references.keys.each do |name|
definitions_for_name(name).each(&:alive!)
end
end

# Utils
Expand Down
8 changes: 4 additions & 4 deletions lib/spoom/deadcode/plugins/action_mailer_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ class ActionMailerPreview < Base

ignore_classes_inheriting_from("ActionMailer::Preview")

sig { override.params(symbol_def: Model::Method, definition: Definition).void }
def on_define_method(symbol_def, definition)
owner = symbol_def.owner
sig { override.params(definition: Model::Method).void }
def on_define_method(definition)
owner = definition.owner
return unless owner.is_a?(Model::Class)

superclass_name = owner.superclass_name
return unless superclass_name

definition.ignored! if superclass_name == "ActionMailer::Preview"
@index.ignore(definition) if superclass_name == "ActionMailer::Preview"
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/spoom/deadcode/plugins/actionpack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ class ActionPack < Base

ignore_classes_named(/Controller$/)

sig { override.params(symbol_def: Model::Method, definition: Definition).void }
def on_define_method(symbol_def, definition)
owner = symbol_def.owner
sig { override.params(definition: Model::Method).void }
def on_define_method(definition)
owner = definition.owner
return unless owner.is_a?(Model::Class)

definition.ignored! if ignored_class_name?(owner.name)
@index.ignore(definition) if ignored_class_name?(owner.name)
end

sig { override.params(send: Send).void }
Expand Down
88 changes: 44 additions & 44 deletions lib/spoom/deadcode/plugins/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,20 +140,20 @@ def initialize(index)
#
# ~~~rb
# class MyPlugin < Spoom::Deadcode::Plugins::Base
# def on_define_accessor(symbol_def, definition)
# definition.ignored! if symbol_def.name == "foo"
# def on_define_accessor(definition)
# @index.ignore(definition) if symbol_def.name == "foo"
# end
# end
# ~~~
sig { params(symbol_def: Model::Attr, definition: Definition).void }
def on_define_accessor(symbol_def, definition)
sig { params(definition: Model::Attr).void }
def on_define_accessor(definition)
# no-op
end

# Do not override this method, use `on_define_accessor` instead.
sig { params(symbol_def: Model::Attr, definition: Definition).void }
def internal_on_define_accessor(symbol_def, definition)
on_define_accessor(symbol_def, definition)
sig { params(definition: Model::Attr).void }
def internal_on_define_accessor(definition)
on_define_accessor(definition)
end

# Called when a class is defined.
Expand All @@ -164,26 +164,26 @@ def internal_on_define_accessor(symbol_def, definition)
#
# ~~~rb
# class MyPlugin < Spoom::Deadcode::Plugins::Base
# def on_define_class(symbol_def, definition)
# definition.ignored! if symbol_def.name == "Foo"
# def on_define_class(definition)
# @index.ignore(definition) if definition.name == "Foo"
# end
# end
# ~~~
sig { params(symbol_def: Model::Class, definition: Definition).void }
def on_define_class(symbol_def, definition)
sig { params(definition: Model::Class).void }
def on_define_class(definition)
# no-op
end

# Do not override this method, use `on_define_class` instead.
sig { params(symbol_def: Model::Class, definition: Definition).void }
def internal_on_define_class(symbol_def, definition)
if ignored_class_name?(symbol_def.name)
definition.ignored!
elsif ignored_subclass?(symbol_def.superclass_name&.delete_prefix("::"))
definition.ignored!
sig { params(definition: Model::Class).void }
def internal_on_define_class(definition)
if ignored_class_name?(definition.name)
@index.ignore(definition)
elsif ignored_subclass?(definition.superclass_name&.delete_prefix("::"))
@index.ignore(definition)
end

on_define_class(symbol_def, definition)
on_define_class(definition)
end

# Called when a constant is defined.
Expand All @@ -194,22 +194,22 @@ def internal_on_define_class(symbol_def, definition)
#
# ~~~rb
# class MyPlugin < Spoom::Deadcode::Plugins::Base
# def on_define_constant(symbol_def, definition)
# definition.ignored! if symbol_def.name == "FOO"
# def on_define_constant(definition)
# @index.ignore(definition) if definition.name == "FOO"
# end
# end
# ~~~
sig { params(symbol_def: Model::Constant, definition: Definition).void }
def on_define_constant(symbol_def, definition)
sig { params(definition: Model::Constant).void }
def on_define_constant(definition)
# no-op
end

# Do not override this method, use `on_define_constant` instead.
sig { params(symbol_def: Model::Constant, definition: Definition).void }
def internal_on_define_constant(symbol_def, definition)
definition.ignored! if ignored_constant_name?(symbol_def.name)
sig { params(definition: Model::Constant).void }
def internal_on_define_constant(definition)
@index.ignore(definition) if ignored_constant_name?(definition.name)

on_define_constant(symbol_def, definition)
on_define_constant(definition)
end

# Called when a method is defined.
Expand All @@ -220,22 +220,22 @@ def internal_on_define_constant(symbol_def, definition)
#
# ~~~rb
# class MyPlugin < Spoom::Deadcode::Plugins::Base
# def on_define_method(symbol_def, symbol)
# definition.ignored! if symbol_def.name == "foo"
# def on_define_method(definition)
# @index.ignore(definition) if definition.name == "foo"
# end
# end
# ~~~
sig { params(symbol_def: Model::Method, definition: Definition).void }
def on_define_method(symbol_def, definition)
sig { params(definition: Model::Method).void }
def on_define_method(definition)
# no-op
end

# Do not override this method, use `on_define_method` instead.
sig { params(symbol_def: Model::Method, definition: Definition).void }
def internal_on_define_method(symbol_def, definition)
definition.ignored! if ignored_method_name?(symbol_def.name)
sig { params(definition: Model::Method).void }
def internal_on_define_method(definition)
@index.ignore(definition) if ignored_method_name?(definition.name)

on_define_method(symbol_def, definition)
on_define_method(definition)
end

# Called when a module is defined.
Expand All @@ -246,34 +246,34 @@ def internal_on_define_method(symbol_def, definition)
#
# ~~~rb
# class MyPlugin < Spoom::Deadcode::Plugins::Base
# def on_define_module(symbol_def, definition)
# definition.ignored! if symbol_def.name == "Foo"
# def on_define_module(definition)
# @index.ignore(definition) if definition.name == "Foo"
# end
# end
# ~~~
sig { params(symbol_def: Model::Module, definition: Definition).void }
def on_define_module(symbol_def, definition)
sig { params(definition: Model::Module).void }
def on_define_module(definition)
# no-op
end

# Do not override this method, use `on_define_module` instead.
sig { params(symbol_def: Model::Module, definition: Definition).void }
def internal_on_define_module(symbol_def, definition)
definition.ignored! if ignored_module_name?(symbol_def.name)
sig { params(definition: Model::Module).void }
def internal_on_define_module(definition)
@index.ignore(definition) if ignored_module_name?(definition.name)

on_define_module(symbol_def, definition)
on_define_module(definition)
end

# Called when a send is being processed
#
# ~~~rb
# class MyPlugin < Spoom::Deadcode::Plugins::Base
# def on_send(indexer, send)
# def on_send(send)
# return unless send.name == "dsl_method"
# return if send.args.empty?
#
# method_name = send.args.first.slice.delete_prefix(":")
# indexer.reference_method(method_name, send.node)
# @index.reference_method(method_name, send.node, send.loc)
# end
# end
# ~~~
Expand Down
8 changes: 4 additions & 4 deletions lib/spoom/deadcode/plugins/minitest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ class Minitest < Base
"teardown",
)

sig { override.params(symbol_def: Model::Method, definition: Definition).void }
def on_define_method(symbol_def, definition)
file = symbol_def.location.file
definition.ignored! if file.match?(%r{test/.*test\.rb$}) && symbol_def.name.match?(/^test_/)
sig { override.params(definition: Model::Method).void }
def on_define_method(definition)
file = definition.location.file
@index.ignore(definition) if file.match?(%r{test/.*test\.rb$}) && definition.name.match?(/^test_/)
end
end
end
Expand Down
12 changes: 6 additions & 6 deletions lib/spoom/deadcode/plugins/namespaces.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ module Plugins
class Namespaces < Base
extend T::Sig

sig { override.params(symbol_def: Model::Class, definition: Definition).void }
def on_define_class(symbol_def, definition)
definition.ignored! if used_as_namespace?(symbol_def)
sig { override.params(definition: Model::Class).void }
def on_define_class(definition)
@index.ignore(definition) if used_as_namespace?(definition)
end

sig { override.params(symbol_def: Model::Module, definition: Definition).void }
def on_define_module(symbol_def, definition)
definition.ignored! if used_as_namespace?(symbol_def)
sig { override.params(definition: Model::Module).void }
def on_define_module(definition)
@index.ignore(definition) if used_as_namespace?(definition)
end

private
Expand Down
Loading

0 comments on commit e5fe37c

Please sign in to comment.