Skip to content

Commit e4cc171

Browse files
authored
Merge pull request #2703 from dduugg/dedupe-duplicate-file-comments
De-duplicate comments shared by multiple definitions
2 parents d3a6e2f + e43ba85 commit e4cc171

2 files changed

Lines changed: 84 additions & 7 deletions

File tree

lib/tapioca/gem/listeners/documentation.rb

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,25 @@ def documentation_comments(name, sigs: [])
6969
end
7070
return [] unless declaration
7171

72-
comments = declaration.definitions.flat_map(&:comments)
73-
comments.uniq!
74-
return [] if comments.empty?
75-
76-
lines = comments
77-
.map { |comment| comment.string.gsub(/^#+ ?/, "") }
78-
.reject { |line| IGNORED_COMMENTS.any? { |comment| line.include?(comment) } || rbs_comment?(line) }
72+
# Definitions often share a comment block, such as a license header, so de-duplicate them
73+
lines = declaration.definitions
74+
.map { |definition| comment_lines(definition) }
75+
.uniq
76+
.flatten
7977

8078
# Strip leading and trailing blank lines, matching YARD's behavior
8179
lines = lines.reverse_each.drop_while(&:empty?).reverse_each.drop_while(&:empty?)
8280

8381
lines.map! { |line| RBI::Comment.new(line) }
8482
end
8583

84+
#: (Rubydex::Definition definition) -> Array[String]
85+
def comment_lines(definition)
86+
lines = definition.comments.map { |comment| comment.string.gsub(/^#+ ?/, "") }
87+
lines.reject! { |line| IGNORED_COMMENTS.any? { |comment| line.include?(comment) } || rbs_comment?(line) }
88+
lines
89+
end
90+
8691
# @override
8792
#: (NodeAdded event) -> bool
8893
def ignore?(event)

spec/tapioca/gem/pipeline_spec.rb

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4468,6 +4468,78 @@ def something; end
44684468
assert_equal(output, compile(include_doc: false))
44694469
end
44704470

4471+
it "does not repeat comments shared by multiple definitions" do
4472+
add_ruby_file("bar.rb", <<~RUBY)
4473+
# rubocop:disable Style/Documentation
4474+
# Licensed under the Foo License, Version 2.0
4475+
module Namespace
4476+
# The answer
4477+
ANSWER = 42
4478+
4479+
# Does the thing
4480+
def self.thing; end
4481+
end
4482+
RUBY
4483+
4484+
add_ruby_file("baz.rb", <<~RUBY)
4485+
# Namespace also holds Baz
4486+
module Namespace
4487+
class Baz; end
4488+
end
4489+
RUBY
4490+
4491+
add_ruby_file("foo.rb", <<~RUBY)
4492+
# Licensed under the Foo License, Version 2.0
4493+
module Namespace
4494+
# The answer
4495+
ANSWER = 42
4496+
4497+
# Does the thing
4498+
def self.thing; end
4499+
end
4500+
RUBY
4501+
4502+
output = template(<<~RBI)
4503+
# Licensed under the Foo License, Version 2.0
4504+
# Namespace also holds Baz
4505+
module Namespace
4506+
class << self
4507+
# Does the thing
4508+
def thing; end
4509+
end
4510+
end
4511+
4512+
# The answer
4513+
Namespace::ANSWER = T.let(T.unsafe(nil), Integer)
4514+
4515+
class Namespace::Baz; end
4516+
RBI
4517+
4518+
assert_equal(output, compile(include_doc: true))
4519+
end
4520+
4521+
it "does not de-duplicate comment blocks that partially overlap" do
4522+
add_ruby_file("bar.rb", <<~RUBY)
4523+
# Licensed under the Foo License, Version 2.0
4524+
module Namespace; end
4525+
RUBY
4526+
4527+
add_ruby_file("foo.rb", <<~RUBY)
4528+
# Licensed under the Foo License, Version 2.0
4529+
# Namespace is defined here because of whatever
4530+
module Namespace; end
4531+
RUBY
4532+
4533+
output = template(<<~RBI)
4534+
# Licensed under the Foo License, Version 2.0
4535+
# Licensed under the Foo License, Version 2.0
4536+
# Namespace is defined here because of whatever
4537+
module Namespace; end
4538+
RBI
4539+
4540+
assert_equal(output, compile(include_doc: true))
4541+
end
4542+
44714543
it "properly processes void in type aliases" do
44724544
add_ruby_file("foo.rb", <<~RUBY)
44734545
module Foo

0 commit comments

Comments
 (0)