Skip to content
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
31 changes: 22 additions & 9 deletions lib/ruby/signature/writer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,8 @@ def write_comment(comment, level:)
end

def write(decls)
decls.each.with_index do |decl, index|
if index > 0
out.puts
end

[nil, *decls].each_cons(2) do |prev, decl|
preserve_empty_line(prev, decl)
write_decl decl
end
end
Expand All @@ -56,10 +53,8 @@ def write_decl(decl)
write_annotation decl.annotations, level: 0
out.puts "class #{name_and_params(decl.name, decl.type_params)}#{super_class}"

decl.members.each.with_index do |member, index|
if index > 0
out.puts
end
[nil, *decl.members].each_cons(2) do |prev, member|
preserve_empty_line prev, member
write_member member
end

Expand Down Expand Up @@ -251,6 +246,24 @@ def attribute(kind, attr)
end
"attr_#{kind} #{attr.name}#{var}: #{attr.type}"
end

def preserve_empty_line(prev, decl)
return unless prev

# When the signature is not constructed by the parser,
# it always inserts an empty line.
unless prev.location
out.puts
return
end

prev_end_line = prev.location.end_line
decl = decl.comment if decl.respond_to?(:comment) && decl.comment
start_line = decl.location.start_line
if start_line - prev_end_line > 1
out.puts
end
end
end
end
end
85 changes: 82 additions & 3 deletions test/ruby/signature/writer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@ class Ruby::Signature::WriterTest < Minitest::Test
Parser = Ruby::Signature::Parser
Writer = Ruby::Signature::Writer

def assert_writer(sig)
Parser.parse_signature(sig).tap do |decls|
def format(sig)
Parser.parse_signature(sig).then do |decls|
writer = Writer.new(out: StringIO.new)
writer.write(decls)

assert_equal sig, writer.out.string
writer.out.string
end
end

def assert_writer(sig)
assert_equal sig, format(sig)
end

def test_const_decl
assert_writer <<-SIG
# World to world.
Expand Down Expand Up @@ -136,4 +140,79 @@ class Foo[out A, unchecked B, in C] < Bar[A, C, B]
end
SIG
end

def test_preserve_empty_line
assert_writer <<-SIG
class Foo
def initialize: () -> void
def foo: () -> void

def bar: () -> void
# comment
def self.foo: () -> void

# comment
def baz: () -> void
end
module Bar
end

class OneEmptyLine
end

# comment
class C
end
# comment
class D
end
SIG
end

def test_remove_double_empty_lines
src = <<-SIG
class Foo

def foo: () -> void


def bar: () -> void
end


module Bar


def foo: () -> void
end
SIG

expected = <<-SIG
class Foo
def foo: () -> void

def bar: () -> void
end

module Bar
def foo: () -> void
end
SIG

assert_equal expected, format(src)

end

def test_smoke
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Pathname.glob('stdlib/**/*.rbs').each do |path|
orig_decls = Ruby::Signature::Parser.parse_signature(path.read)

io = StringIO.new
w = Ruby::Signature::Writer.new(out: io)
w.write(orig_decls)
decls = Ruby::Signature::Parser.parse_signature(io.string)

assert_equal orig_decls, decls
end
end
end