From 1acd4872603eae693c84a12a5dc2fb9a98c572b9 Mon Sep 17 00:00:00 2001
From: Hakan Nilsson <hanilsso@cisco.com>
Date: Tue, 1 Oct 2024 23:17:29 +0200
Subject: [PATCH] Make formatting use in-memory text instead of file content.

This will make document formatting use the unsaved state of the file.
---
 apps/els_lsp/src/els_formatting_provider.erl | 33 ++++++++++++++------
 apps/els_lsp/test/els_formatter_SUITE.erl    |  1 +
 2 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/apps/els_lsp/src/els_formatting_provider.erl b/apps/els_lsp/src/els_formatting_provider.erl
index 6c791710..a09756b6 100644
--- a/apps/els_lsp/src/els_formatting_provider.erl
+++ b/apps/els_lsp/src/els_formatting_provider.erl
@@ -32,11 +32,12 @@ handle_request({document_formatting, Params}) ->
         <<"textDocument">> := #{<<"uri">> := Uri}
     } = Params,
     Path = els_uri:path(Uri),
+    {ok, Document} = els_utils:lookup_document(Uri),
     case els_utils:project_relative(Uri) of
         {error, not_relative} ->
             {response, []};
         RelativePath ->
-            format_document(Path, RelativePath, Options)
+            format_document(Path, Document, RelativePath, Options)
     end;
 handle_request({document_rangeformatting, Params}) ->
     #{
@@ -79,9 +80,9 @@ handle_request({document_ontypeformatting, Params}) ->
 %%==============================================================================
 %% Internal functions
 %%==============================================================================
--spec format_document(binary(), string(), formatting_options()) ->
+-spec format_document(binary(), els_dt_document:item(), string(), formatting_options()) ->
     {response, [text_edit()]}.
-format_document(Path, RelativePath, Options) ->
+format_document(Path, Document, RelativePath, Options) ->
     Config = els_config:get(formatting),
     case {get_formatter_files(Config), get_formatter_exclude_files(Config)} of
         {all, ExcludeFiles} ->
@@ -89,7 +90,7 @@ format_document(Path, RelativePath, Options) ->
                 true ->
                     {response, []};
                 false ->
-                    do_format_document(Path, RelativePath, Options)
+                    do_format_document(Document, RelativePath, Options)
             end;
         {Files, ExcludeFiles} ->
             case lists:member(Path, Files) of
@@ -98,20 +99,32 @@ format_document(Path, RelativePath, Options) ->
                         true ->
                             {response, []};
                         false ->
-                            do_format_document(Path, RelativePath, Options)
+                            do_format_document(Document, RelativePath, Options)
                     end;
                 false ->
                     {response, []}
             end
     end.
 
--spec do_format_document(binary(), string(), formatting_options()) ->
+-spec do_format_document(els_dt_document:item(), string(), formatting_options()) ->
     {response, [text_edit()]}.
-do_format_document(Path, RelativePath, Options) ->
+do_format_document(#{text := Text}, RelativePath, Options) ->
     Fun = fun(Dir) ->
-        format_document_local(Dir, RelativePath, Options),
-        Outfile = filename:join(Dir, RelativePath),
-        {response, els_text_edit:diff_files(Path, Outfile)}
+        {ok, OldCwd} = file:get_cwd(),
+        ok = file:set_cwd(Dir),
+        try
+            Basename = filename:basename(RelativePath),
+            InFile = filename:join(Dir, Basename),
+            OutDir = filename:join([Dir, "formatted"]),
+            OutFile = filename:join(OutDir, Basename),
+            ok = filelib:ensure_dir(OutFile),
+            ok = file:write_file(InFile, Text),
+            ok = format_document_local(OutDir, Basename, Options),
+            Diff = els_text_edit:diff_files(InFile, OutFile),
+            {response, Diff}
+        after
+            ok = file:set_cwd(OldCwd)
+        end
     end,
     tempdir:mktmp(Fun).
 
diff --git a/apps/els_lsp/test/els_formatter_SUITE.erl b/apps/els_lsp/test/els_formatter_SUITE.erl
index 0f0f40e5..7b641a4e 100644
--- a/apps/els_lsp/test/els_formatter_SUITE.erl
+++ b/apps/els_lsp/test/els_formatter_SUITE.erl
@@ -73,6 +73,7 @@ format_doc(Config) ->
     try
         file:set_cwd(RootPath),
         Uri = ?config(format_input_uri, Config),
+        ok = els_config:set(formatting, #{}),
         #{result := Result} = els_client:document_formatting(Uri, 8, true),
         ?assertEqual(
             [