diff --git a/spec/compiler/formatter/formatter_spec.cr b/spec/compiler/formatter/formatter_spec.cr index f0ee8410bd57..4eb8b39bdd9d 100644 --- a/spec/compiler/formatter/formatter_spec.cr +++ b/spec/compiler/formatter/formatter_spec.cr @@ -259,6 +259,177 @@ describe Crystal::Formatter do assert_format "def foo\n 1 #\nrescue\nend" assert_format "def foo\n 1\n #\n\n\nrescue\nend", "def foo\n 1\n #\nrescue\nend" + assert_format "def foo(@[MyAnn] v); end" + assert_format "def foo(@[MyAnn] &); end" + assert_format "def foo(@[MyAnn] &block); end" + assert_format "def foo(@[MyAnn] & : String -> Nil); end" + assert_format "def foo( @[MyAnn] v ); end", "def foo(@[MyAnn] v); end" + assert_format "def foo(@[AnnOne] @[AnnTwo] v); end" + assert_format "def foo(@[AnnOne] @[AnnTwo] v); end", "def foo(@[AnnOne] @[AnnTwo] v); end" + assert_format "def foo(@[AnnOne] @[AnnTwo] & ); end", "def foo(@[AnnOne] @[AnnTwo] &); end" + assert_format "def foo(@[AnnOne] @[AnnTwo] &block : Int32 -> ); end", "def foo(@[AnnOne] @[AnnTwo] &block : Int32 ->); end" + assert_format <<-CRYSTAL + def foo( + @[MyAnn] bar + ); end + CRYSTAL + + assert_format <<-CRYSTAL + def foo( + foo, + @[MyAnn] &block + ); end + CRYSTAL + + assert_format <<-CRYSTAL + def foo( + foo, + @[MyAnn] + &block + ); end + CRYSTAL + + assert_format <<-CRYSTAL + def foo( + foo, + + @[MyAnn] + &block + ); end + CRYSTAL + + assert_format <<-CRYSTAL + def foo( + foo, + + @[MyAnn] + @[MyAnn] + & : Nil -> Nil + ); end + CRYSTAL + + assert_format <<-BEFORE, <<-AFTER + def foo( + @[MyAnn] bar + ); end + BEFORE + def foo( + @[MyAnn] bar + ); end + AFTER + + assert_format <<-CRYSTAL + def foo( + @[MyAnn] + bar + ); end + CRYSTAL + + assert_format <<-CRYSTAL + def foo( + @[MyAnn] + @[MyAnn] + bar + ); end + CRYSTAL + + assert_format <<-CRYSTAL + def foo( + @[MyAnn] + @[MyAnn] + bar, + @[MyAnn] baz + ); end + CRYSTAL + + assert_format <<-CRYSTAL + def foo( + @[MyAnn] + @[MyAnn] + bar, + + @[MyAnn] baz + ); end + CRYSTAL + + assert_format <<-BEFORE, <<-AFTER + def foo( + @[MyAnn] + bar + ); end + BEFORE + def foo( + @[MyAnn] + bar + ); end + AFTER + + assert_format <<-BEFORE, <<-AFTER + def foo( + @[MyAnn] + bar + ); end + BEFORE + def foo( + @[MyAnn] + bar + ); end + AFTER + + assert_format <<-BEFORE + def foo( + @[MyAnn] + @[MyAnn] + bar, + @[MyAnn] @[MyAnn] baz, + @[MyAnn] + @[MyAnn] + biz + ); end + BEFORE + + assert_format <<-BEFORE + def foo( + @[MyAnn] + @[MyAnn] + bar, + + @[MyAnn] @[MyAnn] baz, + + @[MyAnn] + @[MyAnn] + biz + ); end + BEFORE + + assert_format <<-BEFORE, <<-AFTER + def foo( + @[MyAnn] + @[MyAnn] + bar, + + @[MyAnn] @[MyAnn] baz, + + @[MyAnn] + + @[MyAnn] + + biz + ); end + BEFORE + def foo( + @[MyAnn] + @[MyAnn] + bar, + + @[MyAnn] @[MyAnn] baz, + + @[MyAnn] + @[MyAnn] + biz + ); end + AFTER + assert_format "loop do\n 1\nrescue\n 2\nend" assert_format "loop do\n 1\n loop do\n 2\n rescue\n 3\n end\n 4\nend" diff --git a/src/compiler/crystal/tools/formatter.cr b/src/compiler/crystal/tools/formatter.cr index 74a5577485bf..0637207a9f4d 100644 --- a/src/compiler/crystal/tools/formatter.cr +++ b/src/compiler/crystal/tools/formatter.cr @@ -1548,6 +1548,8 @@ module Crystal next if arg.external_name.empty? # skip empty splat argument. end + format_parameter_annotations(arg) + arg.accept self to_skip += 1 if @last_arg_is_skip end @@ -1565,6 +1567,7 @@ module Crystal if block_arg wrote_newline = format_def_arg(wrote_newline, false) do + format_parameter_annotations(block_arg) write_token :OP_AMP skip_space_or_newline @@ -1591,6 +1594,31 @@ module Crystal to_skip end + private def format_parameter_annotations(node) + return unless (anns = node.parsed_annotations) + + anns.each do |ann| + ann.accept self + + skip_space + + if @token.type.newline? + write_line + write_indent + else + write " " + end + + skip_space_or_newline + end + + if @token.type.newline? + skip_space_or_newline + write_line + write_indent + end + end + def format_def_arg(wrote_newline, has_more) write_indent if wrote_newline