11defmodule ElixirLS.LanguageServer.Experimental.Provider.CodeAction.ReplaceRemoteFunctionTest do
2- alias ElixirLS.LanguageServer.Experimental.CodeMod.Diff
32 alias ElixirLS.LanguageServer.Experimental.Protocol.Requests
43 alias ElixirLS.LanguageServer.Experimental.Protocol.Requests.CodeAction , as: CodeActionRequest
54 alias ElixirLS.LanguageServer.Experimental.Protocol.Types.CodeAction
65 alias ElixirLS.LanguageServer.Experimental.Protocol.Types.CodeAction , as: CodeActionReply
76 alias ElixirLS.LanguageServer.Experimental.Protocol.Types.Diagnostic
87 alias ElixirLS.LanguageServer.Experimental.Protocol.Types.Range
9- alias ElixirLS.LanguageServer.Experimental.Protocol.Types.Position
10- alias ElixirLS.LanguageServer.Experimental.Protocol.Types.TextEdit
118 alias ElixirLS.LanguageServer.Experimental.Provider.CodeAction.ReplaceRemoteFunction
129 alias ElixirLS.LanguageServer.Experimental.SourceFile
10+ alias ElixirLS.LanguageServer.Experimental.SourceFile.Document
1311 alias ElixirLS.LanguageServer.Fixtures.LspProtocol
1412 alias ElixirLS.LanguageServer.SourceFile.Path , as: SourceFilePath
1513
@@ -36,10 +34,8 @@ defmodule ElixirLS.LanguageServer.Experimental.Provider.CodeAction.ReplaceRemote
3634 end
3735
3836 defp code_action ( file_body , file_path , line , opts \\ [ ] ) do
39- trimmed_body = String . trim ( file_body , "\n " )
40-
4137 file_uri = SourceFilePath . to_uri ( file_path )
42- SourceFile.Store . open ( file_uri , trimmed_body , 0 )
38+ SourceFile.Store . open ( file_uri , file_body , 0 )
4339
4440 { :ok , range } =
4541 build ( Range ,
@@ -63,43 +59,45 @@ defmodule ElixirLS.LanguageServer.Experimental.Provider.CodeAction.ReplaceRemote
6359 )
6460
6561 { :ok , action } = Requests . to_elixir ( action )
66- { file_uri , action }
62+
63+ { file_uri , file_body , action }
6764 end
6865
69- defp assert_expected_text_edits ( file_uri , action , expected_name , line ) do
70- assert % CodeActionReply { edit: % { changes: % { ^ file_uri => edits } } } = action
66+ defp apply_selected_action ( { file_uri , file_body , code_action } , index ) do
67+ action =
68+ code_action
69+ |> apply ( )
70+ |> Enum . at ( index )
7171
72- expected_edits = Diff . diff ( "counts" , expected_name )
72+ assert % CodeActionReply { edit: % { changes: % { ^ file_uri => edits } } } = action
7373
74- assert edits
75- |> Enum . zip ( expected_edits )
76- |> Enum . all? ( fn { % TextEdit { new_text: new_text } , % TextEdit { new_text: expected_new_text } } ->
77- new_text == expected_new_text
78- end )
74+ { :ok , % SourceFile { document: document } } =
75+ file_uri
76+ |> SourceFile . new ( file_body , 0 )
77+ |> SourceFile . apply_content_changes ( 1 , edits )
7978
80- assert Enum . all? ( edits , fn edit -> edit . range . start . line == line end )
81- assert Enum . all? ( edits , fn edit -> edit . range . end . line == line end )
79+ document
8280 end
8381
8482 test "produces no actions if the function is not found" do
85- assert { _ , action } = code_action ( "Enum.count([1, 2])" , "/project/file.ex" , 0 )
83+ assert { _ , _ , action } = code_action ( "Enum.count([1, 2])" , "/project/file.ex" , 0 )
8684 assert [ ] = apply ( action )
8785 end
8886
8987 test "produces no actions if the line is empty" do
90- { _ , action } = code_action ( "" , "/project/file.ex" , 0 )
88+ { _ , _ , action } = code_action ( "" , "/project/file.ex" , 0 )
9189 assert [ ] = apply ( action )
9290 end
9391
9492 test "produces no results if the diagnostic message doesn't fit the format" do
95- assert { _ , action } =
93+ assert { _ , _ , action } =
9694 code_action ( "" , "/project/file.ex" , 0 , diagnostic_message: "This isn't cool" )
9795
9896 assert [ ] = apply ( action )
9997 end
10098
10199 test "produces no results for buggy source code" do
102- { _ , action } =
100+ { _ , _ , action } =
103101 ~S[
104102 1 + 2~/3 ; 4ab(
105103 ]
@@ -109,72 +107,115 @@ defmodule ElixirLS.LanguageServer.Experimental.Provider.CodeAction.ReplaceRemote
109107 end
110108
111109 test "handles nil context" do
112- assert { _ , action } = code_action ( "other_var = 6" , "/project/file.ex" , 0 )
110+ assert { _ , _ , action } = code_action ( "other_var = 6" , "/project/file.ex" , 0 )
113111
114112 action = put_in ( action , [ :context ] , nil )
115113
116114 assert [ ] = apply ( action )
117115 end
118116
119117 test "handles nil diagnostics" do
120- assert { _ , action } = code_action ( "other_var = 6" , "/project/file.ex" , 0 )
118+ assert { _ , _ , action } = code_action ( "other_var = 6" , "/project/file.ex" , 0 )
121119
122120 action = put_in ( action , [ :context , :diagnostics ] , nil )
123121
124122 assert [ ] = apply ( action )
125123 end
126124
127125 test "handles empty diagnostics" do
128- assert { _ , action } = code_action ( "other_var = 6" , "/project/file.ex" , 0 )
126+ assert { _ , _ , action } = code_action ( "other_var = 6" , "/project/file.ex" , 0 )
129127
130128 action = put_in ( action , [ :context , :diagnostics ] , [ ] )
131129
132130 assert [ ] = apply ( action )
133131 end
134132
135133 test "applied to an isolated function" do
136- { file_uri , code_action } =
137- ~S[
138- Enum.counts(a)
139- ]
140- |> code_action ( "/project/file.ex" , 0 )
141-
142- assert [ to_count_action , to_concat_action ] = apply ( code_action )
143-
144- assert_expected_text_edits ( file_uri , to_count_action , "count" , 0 )
145- assert_expected_text_edits ( file_uri , to_concat_action , "concat" , 0 )
134+ actual_code = ~S[
135+ Enum.counts(a)
136+ ]
137+
138+ expected_doc = ~S[
139+ Enum.count(a)
140+ ] |> Document . new ( )
141+
142+ assert expected_doc ==
143+ actual_code
144+ |> code_action ( "/project/file.ex" , 1 )
145+ |> apply_selected_action ( 0 )
146+
147+ expected_doc = ~S[
148+ Enum.concat(a)
149+ ] |> Document . new ( )
150+
151+ assert expected_doc ==
152+ actual_code
153+ |> code_action ( "/project/file.ex" , 1 )
154+ |> apply_selected_action ( 1 )
146155 end
147156
148157 test "works for a function assigned to a variable" do
149- { file_uri , code_action } =
150- ~S[
151- var = &Enum.counts/1
152- ]
153- |> code_action ( "/project/file.ex" , 0 )
158+ actual_code = ~S[
159+ var = &Enum.counts/1
160+ ]
161+
162+ expected_doc = ~S[
163+ var = &Enum.count/1
164+ ] |> Document . new ( )
165+
166+ assert expected_doc ==
167+ actual_code
168+ |> code_action ( "/project/file.ex" , 1 )
169+ |> apply_selected_action ( 0 )
154170
155- assert [ to_count_action , to_concat_action ] = apply ( code_action )
171+ expected_doc = ~S[
172+ var = &Enum.concat/1
173+ ] |> Document . new ( )
156174
157- assert_expected_text_edits ( file_uri , to_count_action , "count" , 0 )
158- assert_expected_text_edits ( file_uri , to_concat_action , "concat" , 0 )
175+ assert expected_doc ==
176+ actual_code
177+ |> code_action ( "/project/file.ex" , 1 )
178+ |> apply_selected_action ( 1 )
159179 end
160180
161181 test "works with multiple lines" do
162- { file_uri , code_action } = ~S[
182+ actual_code = ~S[
163183 defmodule MyModule do
164184 def my_func(a) do
165185 Enum.counts(a)
166186 end
167187 end
168- ] |> code_action ( "/project/file.ex" , 2 )
188+ ]
169189
170- assert [ to_count_action , to_concat_action ] = apply ( code_action )
190+ expected_doc = ~S[
191+ defmodule MyModule do
192+ def my_func(a) do
193+ Enum.count(a)
194+ end
195+ end
196+ ] |> Document . new ( )
197+
198+ assert expected_doc ==
199+ actual_code
200+ |> code_action ( "/project/file.ex" , 3 )
201+ |> apply_selected_action ( 0 )
171202
172- assert_expected_text_edits ( file_uri , to_count_action , "count" , 2 )
173- assert_expected_text_edits ( file_uri , to_concat_action , "concat" , 2 )
203+ expected_doc = ~S[
204+ defmodule MyModule do
205+ def my_func(a) do
206+ Enum.concat(a)
207+ end
208+ end
209+ ] |> Document . new ( )
210+
211+ assert expected_doc ==
212+ actual_code
213+ |> code_action ( "/project/file.ex" , 3 )
214+ |> apply_selected_action ( 1 )
174215 end
175216
176217 test "proposed functions need to match the replaced function arity" do
177- { _ , code_action } =
218+ { _ , _ , code_action } =
178219 ~S[
179220 Enum.counts(a)
180221 ]
@@ -184,7 +225,7 @@ defmodule ElixirLS.LanguageServer.Experimental.Provider.CodeAction.ReplaceRemote
184225 end
185226
186227 test "does not replace variables" do
187- { _ , code_action } =
228+ { _ , _ , code_action } =
188229 ~S[
189230 counts + 42
190231 ]
@@ -200,58 +241,82 @@ defmodule ElixirLS.LanguageServer.Experimental.Provider.CodeAction.ReplaceRemote
200241 * my_func/1
201242 """
202243
203- code = ~S[
204- defmodule Example do
205- defmodule A.B do
206- def my_func(a), do: a
207- end
244+ actual_code = ~S[
245+ defmodule Example do
246+ defmodule A.B do
247+ def my_func(a), do: a
248+ end
208249
209- defmodule C do
210- def my_fun(a), do: a
211- end
250+ defmodule C do
251+ def my_fun(a), do: a
252+ end
212253
213- defmodule D do
214- alias Example.A
215- alias Example.A.B
216- alias Example.C
217- def bar() do
218- A.B.my_fun(42)
219- C.my_fun(42) + B.my_fun(42)
220- end
254+ defmodule D do
255+ alias Example.A
256+ alias Example.A.B
257+ alias Example.C
258+ def bar() do
259+ A.B.my_fun(42)
260+ C.my_fun(42) + B.my_fun(42)
221261 end
222262 end
263+ end
223264 ]
224265
225266 # A.B.my_fun(42)
226- { file_uri , code_action } =
227- code_action ( code , "/project/file.ex" , 14 , diagnostic_message: diagnostic_message )
267+ expected_doc = ~S[
268+ defmodule Example do
269+ defmodule A.B do
270+ def my_func(a), do: a
271+ end
272+
273+ defmodule C do
274+ def my_fun(a), do: a
275+ end
228276
229- assert [ % CodeActionReply { edit: % { changes: % { ^ file_uri => edits } } } ] = apply ( code_action )
277+ defmodule D do
278+ alias Example.A
279+ alias Example.A.B
280+ alias Example.C
281+ def bar() do
282+ A.B.my_func(42)
283+ C.my_fun(42) + B.my_fun(42)
284+ end
285+ end
286+ end
287+ ] |> Document . new ( )
230288
231- assert [
232- % TextEdit {
233- new_text: "c" ,
234- range: % Range {
235- end: % Position { character: 24 , line: 14 } ,
236- start: % Position { character: 24 , line: 14 }
237- }
238- }
239- ] = edits
289+ assert expected_doc ==
290+ actual_code
291+ |> code_action ( "/project/file.ex" , 15 , diagnostic_message: diagnostic_message )
292+ |> apply_selected_action ( 0 )
240293
241294 # B.my_fun(42)
242- { file_uri , code_action } =
243- code_action ( code , "/project/file.ex" , 15 , diagnostic_message: diagnostic_message )
244-
245- assert [ % CodeActionReply { edit: % { changes: % { ^ file_uri => edits } } } ] = apply ( code_action )
246-
247- assert [
248- % TextEdit {
249- new_text: "c" ,
250- range: % Range {
251- end: % Position { character: 37 , line: 15 } ,
252- start: % Position { character: 37 , line: 15 }
253- }
254- }
255- ] = edits
295+ expected_doc = ~S[
296+ defmodule Example do
297+ defmodule A.B do
298+ def my_func(a), do: a
299+ end
300+
301+ defmodule C do
302+ def my_fun(a), do: a
303+ end
304+
305+ defmodule D do
306+ alias Example.A
307+ alias Example.A.B
308+ alias Example.C
309+ def bar() do
310+ A.B.my_fun(42)
311+ C.my_fun(42) + B.my_func(42)
312+ end
313+ end
314+ end
315+ ] |> Document . new ( )
316+
317+ assert expected_doc ==
318+ actual_code
319+ |> code_action ( "/project/file.ex" , 16 , diagnostic_message: diagnostic_message )
320+ |> apply_selected_action ( 0 )
256321 end
257322end
0 commit comments