Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Also check duplicated mixins in shims and TODO files #1077

Merged
merged 1 commit into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/tapioca/helpers/rbi_files_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ def shims_or_todos_have_duplicates?(nodes, shim_rbi_dir:, todo_rbi_file:)
shims_or_todos_empty_scopes = extract_empty_scopes(shims_or_todos)
return true unless shims_or_todos_empty_scopes.empty?

mixins = extract_mixins(shims_or_todos)
return true unless mixins.empty?

props = extract_methods_and_attrs(shims_or_todos)
return false if props.empty?

Expand Down Expand Up @@ -215,6 +218,13 @@ def extract_methods_and_attrs(nodes)
end, T::Array[T.any(RBI::Method, RBI::Attr)])
end

sig { params(nodes: T::Array[RBI::Node]).returns(T::Array[T.any(RBI::Mixin, RBI::RequiresAncestor)]) }
def extract_mixins(nodes)
T.cast(nodes.select do |node|
node.is_a?(RBI::Mixin) || node.is_a?(RBI::RequiresAncestor)
end, T::Array[T.all(RBI::Mixin, RBI::RequiresAncestor)])
end

sig { params(nodes: T::Array[T.any(RBI::Method, RBI::Attr)]).returns(T::Array[T.any(RBI::Method, RBI::Attr)]) }
def extract_nodes_with_sigs(nodes)
nodes.reject { |node| node.sigs.empty? }
Expand Down
67 changes: 67 additions & 0 deletions spec/tapioca/cli/check_shims_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,73 @@ class Foo
refute_success_status(result)
end

it "detects duplicated includes and extends" do
@project.write("sorbet/rbi/gems/[email protected]", <<~RBI)
module Bar; end

class Foo
include Bar
extend Bar
mixes_in_class_methods Bar
requires_ancestor { Bar }
end

module Baz; end

class Qux
# RBI does not attempt to resolve constants used in the mixins, so if the constant duplicated in the shim
# does not use the same namespace, Tapioca won't catch it. The following lines won't raise duplication
# errors.
include Baz
extend Baz
mixes_in_class_methods Baz
requires_ancestor { Baz }
end
RBI

@project.write("sorbet/rbi/shims/foo.rbi", <<~RBI)
class Foo
include Bar
extend Bar
mixes_in_class_methods Bar
requires_ancestor { Bar }
end

class Qux
include ::Baz
extend ::Baz
mixes_in_class_methods ::Baz
requires_ancestor { ::Baz }
end
RBI

result = @project.tapioca("check-shims --no-payload")

assert_includes(result.err, <<~ERR)
Duplicated RBI for ::Foo.include(Bar):
* sorbet/rbi/shims/foo.rbi:2:2-2:13
* sorbet/rbi/gems/[email protected]:4:2-4:13

Duplicated RBI for ::Foo.extend(Bar):
* sorbet/rbi/shims/foo.rbi:3:2-3:12
* sorbet/rbi/gems/[email protected]:5:2-5:12

Duplicated RBI for ::Foo.mixes_in_class_method(Bar):
* sorbet/rbi/shims/foo.rbi:4:2-4:28
* sorbet/rbi/gems/[email protected]:6:2-6:28

Duplicated RBI for ::Foo.requires_ancestor(Bar):
* sorbet/rbi/shims/foo.rbi:5:2-5:27
* sorbet/rbi/gems/[email protected]:7:2-7:27
ERR

assert_includes(result.err, <<~ERR)
Please remove the duplicated definitions from sorbet/rbi/shims and sorbet/rbi/todo.rbi
ERR

refute_success_status(result)
end

it "detects duplicates from same shim file" do
@project.write("sorbet/rbi/gems/[email protected]", <<~RBI)
class Foo
Expand Down