@@ -23,16 +23,6 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
23
23
:command
24
24
]
25
25
26
- # Format:
27
- # {name, snippet, documentation, priority}
28
- @ module_attr_snippets [
29
- { ~s( doc """""") , ~s( doc """\n $0\n """) , "Documents a function" , 3 } ,
30
- { "doc false" , "doc false" , "Marks this function as internal" , 5 } ,
31
- { ~s( moduledoc """""") , ~s( moduledoc """\n $0\n """) , "Documents a module" , 3 } ,
32
- { "moduledoc false" , "moduledoc false" , "Marks this module as internal" , 5 } ,
33
- { "typedoc" , ~s( typedoc """\n $0\n """) , "Documents a type specification" , 3 }
34
- ]
35
-
36
26
@ func_snippets % {
37
27
{ "Kernel.SpecialForms" , "case" } => "case $1 do\n \t $2 ->\n \t \t $0\n end" ,
38
28
{ "Kernel.SpecialForms" , "with" } => "with $2 <- $1 do\n \t $0\n end" ,
@@ -140,7 +130,6 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
140
130
ElixirSense . suggestions ( text , line + 1 , character + 1 )
141
131
|> maybe_reject_derived_functions ( context , options )
142
132
|> Enum . map ( & from_completion_item ( & 1 , context , options ) )
143
- |> Enum . concat ( module_attr_snippets ( context ) )
144
133
145
134
items_json =
146
135
items
@@ -171,10 +160,12 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
171
160
capture_before? = context . capture_before?
172
161
173
162
Enum . reject ( suggestions , fn s ->
174
- s . type in [ :function , :macro ] && ! capture_before? && s . arity < s . def_arity &&
175
- signature_help_supported &&
176
- function_name_with_parens? ( s . name , s . arity , locals_without_parens ) &&
177
- function_name_with_parens? ( s . name , s . def_arity , locals_without_parens )
163
+ s . type in [ :function , :macro ] and
164
+ ! capture_before? and
165
+ s . arity < s . def_arity and
166
+ signature_help_supported and
167
+ function_name_with_parens? ( s . name , s . arity , locals_without_parens ) ==
168
+ function_name_with_parens? ( s . name , s . def_arity , locals_without_parens )
178
169
end )
179
170
end
180
171
@@ -200,7 +191,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
200
191
detail: "module attribute" ,
201
192
insert_text: insert_text ,
202
193
filter_text: name_only ,
203
- priority: 4 ,
194
+ priority: 14 ,
204
195
tags: [ ]
205
196
}
206
197
end
@@ -220,7 +211,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
220
211
kind: :variable ,
221
212
detail: "variable" ,
222
213
insert_text: name ,
223
- priority: 3 ,
214
+ priority: 13 ,
224
215
tags: [ ]
225
216
}
226
217
end
@@ -238,7 +229,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
238
229
detail: "return value" ,
239
230
documentation: spec ,
240
231
insert_text: snippet ,
241
- priority: 5 ,
232
+ priority: 15 ,
242
233
tags: [ ]
243
234
}
244
235
end
@@ -272,7 +263,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
272
263
documentation: summary ,
273
264
insert_text: name ,
274
265
filter_text: name ,
275
- priority: 4 ,
266
+ priority: 14 ,
276
267
tags: metadata_to_tags ( metadata )
277
268
}
278
269
end
@@ -322,7 +313,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
322
313
detail: "#{ origin } callback" ,
323
314
documentation: summary ,
324
315
insert_text: insert_text ,
325
- priority: 2 ,
316
+ priority: 12 ,
326
317
filter_text: filter_text ,
327
318
tags: metadata_to_tags ( metadata )
328
319
}
@@ -354,7 +345,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
354
345
detail: "#{ origin } protocol function" ,
355
346
documentation: summary ,
356
347
insert_text: insert_text ,
357
- priority: 2 ,
348
+ priority: 12 ,
358
349
filter_text: name ,
359
350
tags: metadata_to_tags ( metadata )
360
351
}
@@ -376,7 +367,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
376
367
label: to_string ( name ) ,
377
368
detail: detail ,
378
369
insert_text: if ( call? , do: name , else: "#{ name } : " ) ,
379
- priority: 0 ,
370
+ priority: 10 ,
380
371
kind: :field ,
381
372
tags: [ ]
382
373
}
@@ -398,7 +389,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
398
389
detail: "#{ type_spec } " ,
399
390
documentation: "#{ doc } #{ formatted_spec } " ,
400
391
insert_text: "#{ name } : " ,
401
- priority: 0 ,
392
+ priority: 10 ,
402
393
kind: :field ,
403
394
tags: [ ]
404
395
}
@@ -431,12 +422,38 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
431
422
detail: "typespec #{ signature } " ,
432
423
documentation: "#{ doc } #{ formatted_spec } " ,
433
424
insert_text: snippet ,
434
- priority: 0 ,
425
+ priority: 10 ,
435
426
kind: :class ,
436
427
tags: metadata_to_tags ( metadata )
437
428
}
438
429
end
439
430
431
+ defp from_completion_item ( % { type: :generic , kind: kind , label: label } = suggestion , _ctx , opts ) do
432
+ insert_text =
433
+ cond do
434
+ suggestion [ :snippet ] && Keyword . get ( opts , :snippets_supported , false ) ->
435
+ suggestion [ :snippet ]
436
+
437
+ insert_text = suggestion [ :insert_text ] ->
438
+ insert_text
439
+
440
+ true ->
441
+ label
442
+ end
443
+
444
+ % __MODULE__ {
445
+ label: label ,
446
+ detail: suggestion [ :detail ] || "" ,
447
+ documentation: suggestion [ :documentation ] || "" ,
448
+ insert_text: insert_text ,
449
+ filter_text: suggestion [ :filter_text ] ,
450
+ priority: suggestion [ :priority ] || 0 ,
451
+ kind: kind ,
452
+ command: suggestion [ :command ] ,
453
+ tags: [ ]
454
+ }
455
+ end
456
+
440
457
defp from_completion_item (
441
458
% { name: name , origin: origin } = item ,
442
459
% { def_before: nil } = context ,
@@ -446,7 +463,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
446
463
447
464
completion =
448
465
if origin == "Kernel" || origin == "Kernel.SpecialForms" do
449
- % { completion | kind: :keyword , priority: 8 }
466
+ % { completion | kind: :keyword , priority: 18 }
450
467
else
451
468
completion
452
469
end
@@ -474,21 +491,31 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
474
491
snippets_supported? = Keyword . get ( opts , :snippets_supported , false )
475
492
trigger_signature? = Keyword . get ( opts , :trigger_signature? , false )
476
493
capture_before? = Keyword . get ( opts , :capture_before? , false )
494
+ pipe_before? = Keyword . get ( opts , :pipe_before? , false )
495
+ with_parens? = Keyword . get ( opts , :with_parens? , false )
496
+ snippet = Keyword . get ( opts , :snippet )
477
497
478
498
cond do
499
+ snippet && snippets_supported? && ! pipe_before? && ! capture_before? ->
500
+ snippet
501
+
479
502
capture_before? ->
480
503
function_snippet_with_capture_before ( name , arity , snippets_supported? )
481
504
482
505
trigger_signature? ->
483
506
text_after_cursor = Keyword . get ( opts , :text_after_cursor , "" )
484
- function_snippet_with_signature ( name , text_after_cursor , snippets_supported? )
507
+
508
+ function_snippet_with_signature (
509
+ name ,
510
+ text_after_cursor ,
511
+ snippets_supported? ,
512
+ with_parens?
513
+ )
485
514
486
515
has_text_after_cursor? ( opts ) ->
487
516
name
488
517
489
518
snippets_supported? ->
490
- pipe_before? = Keyword . get ( opts , :pipe_before? , false )
491
- with_parens? = Keyword . get ( opts , :with_parens? , false )
492
519
function_snippet_with_args ( name , arity , args , pipe_before? , with_parens? )
493
520
494
521
true ->
@@ -526,14 +553,19 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
526
553
Enum . join ( [ name , before_args , Enum . join ( tabstops , ", " ) , after_args ] )
527
554
end
528
555
529
- defp function_snippet_with_signature ( name , text_after_cursor , snippets_supported? ) do
530
- # Don't add the closing parenthesis to the snippet if the cursor is
531
- # immediately before a valid argument. This usually happens when we
532
- # want to wrap an existing variable or literal, e.g. using IO.inspect/2.
533
- if ! snippets_supported? || Regex . match? ( ~r/ ^[a-zA-Z0-9_:"'%<@\[ \{ ]/ , text_after_cursor ) do
534
- "#{ name } ("
535
- else
536
- "#{ name } ($1)$0"
556
+ defp function_snippet_with_signature ( name , text_after_cursor , snippets_supported? , with_parens? ) do
557
+ cond do
558
+ ! with_parens? ->
559
+ if String . starts_with? ( text_after_cursor , " " ) , do: name , else: "#{ name } "
560
+
561
+ # Don't add the closing parenthesis to the snippet if the cursor is
562
+ # immediately before a valid argument. This usually happens when we
563
+ # want to wrap an existing variable or literal, e.g. using IO.inspect/2.
564
+ ! snippets_supported? || Regex . match? ( ~r/ ^[a-zA-Z0-9_:"'%<@\[ \{ ]/ , text_after_cursor ) ->
565
+ "#{ name } ("
566
+
567
+ true ->
568
+ "#{ name } ($1)$0"
537
569
end
538
570
end
539
571
@@ -578,6 +610,13 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
578
610
:color -> 16
579
611
:file -> 17
580
612
:reference -> 18
613
+ :folder -> 19
614
+ :enum_member -> 20
615
+ :constant -> 21
616
+ :struct -> 22
617
+ :event -> 23
618
+ :operator -> 24
619
+ :type_parameter -> 25
581
620
end
582
621
end
583
622
@@ -626,31 +665,6 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
626
665
result
627
666
end
628
667
629
- defp module_attr_snippets ( % { prefix: prefix , scope: :module , def_before: nil } ) do
630
- for { name , snippet , docs , priority } <- @ module_attr_snippets ,
631
- label = "@" <> name ,
632
- String . starts_with? ( label , prefix ) do
633
- snippet =
634
- case prefix do
635
- "@" <> _ -> snippet
636
- _ -> "@" <> snippet
637
- end
638
-
639
- % __MODULE__ {
640
- label: label ,
641
- kind: :snippet ,
642
- documentation: docs ,
643
- detail: "module attribute snippet" ,
644
- insert_text: snippet ,
645
- filter_text: name ,
646
- tags: [ ] ,
647
- priority: priority
648
- }
649
- end
650
- end
651
-
652
- defp module_attr_snippets ( _ ) , do: [ ]
653
-
654
668
defp function_completion ( info , context , options ) do
655
669
% {
656
670
type: type ,
@@ -675,10 +689,10 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
675
689
676
690
locals_without_parens = Keyword . get ( options , :locals_without_parens )
677
691
signature_help_supported? = Keyword . get ( options , :signature_help_supported , false )
692
+ signature_after_complete? = Keyword . get ( options , :signature_after_complete , true )
678
693
with_parens? = function_name_with_parens? ( name , arity , locals_without_parens )
679
694
680
- trigger_signature? =
681
- signature_help_supported? && with_parens? && ( ( arity == 1 && ! pipe_before? ) || arity > 1 )
695
+ trigger_signature? = signature_help_supported? && ( ( arity == 1 && ! pipe_before? ) || arity > 1 )
682
696
683
697
{ label , insert_text } =
684
698
cond do
@@ -702,10 +716,12 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
702
716
options ,
703
717
pipe_before?: pipe_before? ,
704
718
capture_before?: capture_before? ,
719
+ pipe_before?: pipe_before? ,
705
720
trigger_signature?: trigger_signature? ,
706
721
locals_without_parens: locals_without_parens ,
707
722
text_after_cursor: text_after_cursor ,
708
- with_parens?: with_parens?
723
+ with_parens?: with_parens? ,
724
+ snippet: info [ :snippet ]
709
725
)
710
726
)
711
727
@@ -724,7 +740,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
724
740
footer = SourceFile . format_spec ( spec , line_length: 30 )
725
741
726
742
command =
727
- if trigger_signature? && ! capture_before? do
743
+ if trigger_signature? && signature_after_complete? && ! capture_before? do
728
744
% {
729
745
"title" => "Trigger Parameter Hint" ,
730
746
"command" => "editor.action.triggerParameterHints"
@@ -737,7 +753,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
737
753
detail: detail ,
738
754
documentation: summary <> footer ,
739
755
insert_text: insert_text ,
740
- priority: 7 ,
756
+ priority: 17 ,
741
757
tags: metadata_to_tags ( metadata ) ,
742
758
command: command
743
759
}
0 commit comments