diff --git a/lib/elixir/lib/code/formatter.ex b/lib/elixir/lib/code/formatter.ex index 909a9f05d7..10a5dcc66e 100644 --- a/lib/elixir/lib/code/formatter.ex +++ b/lib/elixir/lib/code/formatter.ex @@ -393,10 +393,17 @@ defmodule Code.Formatter do end # foo[bar] - defp quoted_to_algebra({{:., _, [Access, :get]}, meta, [target | args]}, _context, state) do + defp quoted_to_algebra({{:., _, [Access, :get]}, meta, [target, arg]}, _context, state) do {target_doc, state} = remote_target_to_algebra(target, state) - {call_doc, state} = list_to_algebra(meta, args, state) - {concat(target_doc, call_doc), state} + + {access_doc, state} = + if keyword?(arg) do + list_to_algebra(meta, arg, state) + else + list_to_algebra(meta, [arg], state) + end + + {concat(target_doc, access_doc), state} end # %Foo{} diff --git a/lib/elixir/src/elixir_parser.yrl b/lib/elixir/src/elixir_parser.yrl index 3d596174d1..6631d9cecd 100644 --- a/lib/elixir/src/elixir_parser.yrl +++ b/lib/elixir/src/elixir_parser.yrl @@ -285,9 +285,9 @@ number -> char : handle_number(?exprs('$1'), '$1', number_value('$1')). parens_call -> dot_call_identifier call_args_parens : build_parens('$1', '$2', {[], []}). parens_call -> dot_call_identifier call_args_parens call_args_parens : build_nested_parens('$1', '$2', '$3', {[], []}). -bracket_arg -> open_bracket kw close_bracket : build_list('$1', '$2', '$3'). -bracket_arg -> open_bracket container_expr close_bracket : build_list('$1', '$2', '$3'). -bracket_arg -> open_bracket container_expr ',' close_bracket : build_list('$1', '$2', '$4'). +bracket_arg -> open_bracket kw close_bracket : build_access_arg('$1', '$2', '$3'). +bracket_arg -> open_bracket container_expr close_bracket : build_access_arg('$1', '$2', '$3'). +bracket_arg -> open_bracket container_expr ',' close_bracket : build_access_arg('$1', '$2', '$4'). bracket_expr -> dot_bracket_identifier bracket_arg : build_access(build_no_parens('$1', nil), '$2'). bracket_expr -> access_expr bracket_arg : build_access('$1', '$2'). @@ -882,8 +882,10 @@ build_fn(Fn, Stab, End) -> %% Access -build_access(Expr, {List, Location}) -> - Meta = meta_from_location(Location), +build_access_arg(Left, Args, Right) -> + {Args, newlines_pair(Left, Right) ++ meta_from_token(Left)}. + +build_access(Expr, {List, Meta}) -> {{'.', Meta, ['Elixir.Access', get]}, Meta, [Expr, List]}. %% Interpolation aware diff --git a/lib/elixir/test/elixir/code_formatter/calls_test.exs b/lib/elixir/test/elixir/code_formatter/calls_test.exs index db78baa143..cd07a0431c 100644 --- a/lib/elixir/test/elixir/code_formatter/calls_test.exs +++ b/lib/elixir/test/elixir/code_formatter/calls_test.exs @@ -1215,7 +1215,9 @@ defmodule Code.Formatter.CallsTest do end test "with keywords" do - assert_format "expr[foo: bar, baz: bat]", "expr[[foo: bar, baz: bat]]" + assert_format "expr[[]]", "expr[[]]" + assert_format "expr[foo: bar, baz: bat]", "expr[foo: bar, baz: bat]" + assert_format "expr[[foo: bar, baz: bat]]", "expr[[foo: bar, baz: bat]]" end end end diff --git a/lib/elixir/test/elixir/code_formatter/comments_test.exs b/lib/elixir/test/elixir/code_formatter/comments_test.exs index 99e373f90c..288cc22460 100644 --- a/lib/elixir/test/elixir/code_formatter/comments_test.exs +++ b/lib/elixir/test/elixir/code_formatter/comments_test.exs @@ -358,6 +358,30 @@ defmodule Code.Formatter.CommentsTest do end end + describe "access" do + test "before and after single arg" do + assert_same ~S""" + foo[ + # bar + baz + # bat + ] + """ + end + + test "before and after keywords" do + assert_same ~S""" + foo[ + # bar + one: :two, + # baz + three: :four + # bat + ] + """ + end + end + describe "calls" do test "local with parens inside before and after" do assert_same ~S"""