From 60b58037ebf851f2befc4970a9d946e22b3ef2e4 Mon Sep 17 00:00:00 2001 From: robmckinnon Date: Sun, 12 Mar 2023 08:05:18 +0000 Subject: [PATCH] Add :include_comments option to Ast.from/2 Use Sourceror.parse_string/1 when include_comments: true. --- .../experimental/code_mod/ast.ex | 16 ++-- .../test/experimental/code_mod/ast_test.exs | 86 +++++++++++++++++++ 2 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 apps/language_server/test/experimental/code_mod/ast_test.exs diff --git a/apps/language_server/lib/language_server/experimental/code_mod/ast.ex b/apps/language_server/lib/language_server/experimental/code_mod/ast.ex index a7ddfd3af..4f99a01cd 100644 --- a/apps/language_server/lib/language_server/experimental/code_mod/ast.ex +++ b/apps/language_server/lib/language_server/experimental/code_mod/ast.ex @@ -10,15 +10,21 @@ defmodule ElixirLS.LanguageServer.Experimental.CodeMod.Ast do | {any(), any()} | {atom() | {any(), [any()], atom() | [any()]}, Keyword.t(), atom() | [any()]} - @spec from(source) :: t - def from(%SourceFile{} = source_file) do + def from(source_file, opts \\ []) + + @spec from(source, keyword()) :: t + def from(%SourceFile{} = source_file, opts) do source_file |> SourceFile.to_string() - |> from() + |> from(opts) end - def from(s) when is_binary(s) do - ElixirSense.string_to_quoted(s, 1, 6, token_metadata: true) + def from(s, opts) when is_binary(s) do + if opts[:include_comments] do + Sourceror.parse_string(s) + else + ElixirSense.string_to_quoted(s, 1, 6, token_metadata: true) + end end @spec to_string(t()) :: String.t() diff --git a/apps/language_server/test/experimental/code_mod/ast_test.exs b/apps/language_server/test/experimental/code_mod/ast_test.exs new file mode 100644 index 000000000..c5e607793 --- /dev/null +++ b/apps/language_server/test/experimental/code_mod/ast_test.exs @@ -0,0 +1,86 @@ +defmodule ElixirLS.LanguageServer.Experimental.CodeMod.AstTest do + alias ElixirLS.LanguageServer.Experimental.CodeMod.Ast + + use ExUnit.Case + + describe "ast" do + test "from\2 / to_string\1" do + string = """ + defmodule Bar do + def foo(baz) do + # TODO + end + end + """ + + {:ok, ast} = Ast.from(string, include_comments: true) + assert string == Ast.to_string(ast) <> "\n" + + {:ok, ast_missing_comments} = Ast.from(string) + + assert """ + defmodule Bar do + def foo(baz) do + end + end + """ == Ast.to_string(ast_missing_comments) <> "\n" + end + + test "from\1" do + assert {:ok, + {:def, [do: [line: 1, column: 16], end: [line: 3, column: 3], line: 1, column: 3], + [ + {:foo, [closing: [line: 1, column: 14], line: 1, column: 7], + [{:baz, [line: 1, column: 11], nil}]}, + [do: {:__block__, [], []}] + ]}} = + Ast.from(""" + def foo(baz) do + # TODO + end + """) + end + + test "from\2" do + assert {:ok, + {:def, + [ + trailing_comments: [ + %{column: 5, line: 2, next_eol_count: 1, previous_eol_count: 1, text: "# TODO"} + ], + leading_comments: [], + do: [line: 1, column: 16], + end: [line: 3, column: 3], + line: 1, + column: 3 + ], + [ + {:foo, + [ + trailing_comments: [], + leading_comments: [], + closing: [line: 1, column: 14], + line: 1, + column: 7 + ], + [ + {:baz, [trailing_comments: [], leading_comments: [], line: 1, column: 11], + nil} + ]}, + [ + {{:__block__, + [trailing_comments: [], leading_comments: [], line: 1, column: 16], [:do]}, + {:__block__, [trailing_comments: [], leading_comments: []], []}} + ] + ]}} = + Ast.from( + """ + def foo(baz) do + # TODO + end + """, + include_comments: true + ) + end + end +end