@@ -15,18 +15,20 @@ use lsp_types::{CompletionItem, CompletionItemKind, CompletionParams, Completion
15
15
use noirc_errors:: { Location , Span } ;
16
16
use noirc_frontend:: {
17
17
ast:: {
18
- AsTraitPath , BlockExpression , ConstructorExpression , Expression , ForLoopStatement , Ident ,
19
- IfExpression , LValue , Lambda , LetStatement , MemberAccessExpression , NoirFunction ,
20
- NoirStruct , NoirTraitImpl , Path , PathKind , PathSegment , Pattern , Statement , TraitItem ,
21
- TypeImpl , UnresolvedGeneric , UnresolvedGenerics , UnresolvedType , UseTree , UseTreeKind ,
18
+ AsTraitPath , BlockExpression , CallExpression , ConstructorExpression , Expression ,
19
+ ExpressionKind , ForLoopStatement , Ident , IfExpression , LValue , Lambda , LetStatement ,
20
+ MemberAccessExpression , MethodCallExpression , NoirFunction , NoirStruct , NoirTraitImpl ,
21
+ Path , PathKind , PathSegment , Pattern , Statement , StatementKind , TraitItem , TypeImpl ,
22
+ UnresolvedGeneric , UnresolvedGenerics , UnresolvedType , UnresolvedTypeData , UseTree ,
23
+ UseTreeKind ,
22
24
} ,
23
25
graph:: { CrateId , Dependency } ,
24
26
hir:: {
25
27
def_map:: { CrateDefMap , LocalModuleId , ModuleId } ,
26
28
resolution:: path_resolver:: { PathResolver , StandardPathResolver } ,
27
29
} ,
28
30
hir_def:: traits:: Trait ,
29
- macros_api:: { ExpressionKind , ModuleDefId , NodeInterner , StatementKind , UnresolvedTypeData } ,
31
+ macros_api:: { ModuleDefId , NodeInterner } ,
30
32
node_interner:: ReferenceId ,
31
33
parser:: { Item , ItemKind } ,
32
34
ParsedModule , StructType , Type ,
@@ -337,6 +339,71 @@ impl<'a> NodeFinder<'a> {
337
339
}
338
340
}
339
341
342
+ pub ( super ) fn find_in_call_expression ( & mut self , call_expression : & CallExpression ) {
343
+ // Check if it's this case:
344
+ //
345
+ // foo::b>|<(...)
346
+ //
347
+ // In this case we want to suggest items in foo but if they are functions
348
+ // we don't want to insert arguments, because they are already there (even if
349
+ // they could be wrong) just because inserting them would lead to broken code.
350
+ if let ExpressionKind :: Variable ( path) = & call_expression. func . kind {
351
+ if self . includes_span ( path. span ) {
352
+ self . find_in_path_impl ( path, RequestedItems :: AnyItems , true ) ;
353
+ return ;
354
+ }
355
+ }
356
+
357
+ // Check if it's this case:
358
+ //
359
+ // foo.>|<(...)
360
+ //
361
+ // "foo." is actually broken, but it's parsed as "foo", so this is seen
362
+ // as "foo(...)" but if we are at a dot right after "foo" it means it's
363
+ // the above case and we want to suggest methods of foo's type.
364
+ let after_dot = self . byte == Some ( b'.' ) ;
365
+ if after_dot && call_expression. func . span . end ( ) as usize == self . byte_index - 1 {
366
+ let location = Location :: new ( call_expression. func . span , self . file ) ;
367
+ if let Some ( typ) = self . interner . type_at_location ( location) {
368
+ let typ = typ. follow_bindings ( ) ;
369
+ let prefix = "" ;
370
+ self . complete_type_fields_and_methods ( & typ, prefix, FunctionCompletionKind :: Name ) ;
371
+ return ;
372
+ }
373
+ }
374
+
375
+ self . find_in_expression ( & call_expression. func ) ;
376
+ self . find_in_expressions ( & call_expression. arguments ) ;
377
+ }
378
+
379
+ pub ( super ) fn find_in_method_call_expression (
380
+ & mut self ,
381
+ method_call_expression : & MethodCallExpression ,
382
+ ) {
383
+ // Check if it's this case:
384
+ //
385
+ // foo.b>|<(...)
386
+ //
387
+ // In this case we want to suggest items in foo but if they are functions
388
+ // we don't want to insert arguments, because they are already there (even if
389
+ // they could be wrong) just because inserting them would lead to broken code.
390
+ if self . includes_span ( method_call_expression. method_name . span ( ) ) {
391
+ let location = Location :: new ( method_call_expression. object . span , self . file ) ;
392
+ if let Some ( typ) = self . interner . type_at_location ( location) {
393
+ let typ = typ. follow_bindings ( ) ;
394
+ let prefix = method_call_expression. method_name . to_string ( ) ;
395
+ let offset =
396
+ self . byte_index - method_call_expression. method_name . span ( ) . start ( ) as usize ;
397
+ let prefix = prefix[ 0 ..offset] . to_string ( ) ;
398
+ self . complete_type_fields_and_methods ( & typ, & prefix, FunctionCompletionKind :: Name ) ;
399
+ return ;
400
+ }
401
+ }
402
+
403
+ self . find_in_expression ( & method_call_expression. object ) ;
404
+ self . find_in_expressions ( & method_call_expression. arguments ) ;
405
+ }
406
+
340
407
fn find_in_block_expression ( & mut self , block_expression : & BlockExpression ) {
341
408
let old_local_variables = self . local_variables . clone ( ) ;
342
409
for statement in & block_expression. statements {
@@ -417,7 +484,11 @@ impl<'a> NodeFinder<'a> {
417
484
{
418
485
let typ = self . interner . definition_type ( definition_id) ;
419
486
let prefix = "" ;
420
- self . complete_type_fields_and_methods ( & typ, prefix) ;
487
+ self . complete_type_fields_and_methods (
488
+ & typ,
489
+ prefix,
490
+ FunctionCompletionKind :: NameAndParameters ,
491
+ ) ;
421
492
}
422
493
}
423
494
}
@@ -507,7 +578,11 @@ impl<'a> NodeFinder<'a> {
507
578
if let Some ( typ) = self . interner . type_at_location ( location) {
508
579
let typ = typ. follow_bindings ( ) ;
509
580
let prefix = "" ;
510
- self . complete_type_fields_and_methods ( & typ, prefix) ;
581
+ self . complete_type_fields_and_methods (
582
+ & typ,
583
+ prefix,
584
+ FunctionCompletionKind :: NameAndParameters ,
585
+ ) ;
511
586
}
512
587
}
513
588
}
@@ -569,7 +644,11 @@ impl<'a> NodeFinder<'a> {
569
644
if let Some ( typ) = self . interner . type_at_location ( location) {
570
645
let typ = typ. follow_bindings ( ) ;
571
646
let prefix = ident. to_string ( ) . to_case ( Case :: Snake ) ;
572
- self . complete_type_fields_and_methods ( & typ, & prefix) ;
647
+ self . complete_type_fields_and_methods (
648
+ & typ,
649
+ & prefix,
650
+ FunctionCompletionKind :: NameAndParameters ,
651
+ ) ;
573
652
return ;
574
653
}
575
654
}
@@ -662,15 +741,61 @@ impl<'a> NodeFinder<'a> {
662
741
}
663
742
664
743
fn find_in_path ( & mut self , path : & Path , requested_items : RequestedItems ) {
665
- // Only offer completions if we are right at the end of the path
666
- if self . byte_index != path. span . end ( ) as usize {
744
+ self . find_in_path_impl ( path, requested_items, false ) ;
745
+ }
746
+
747
+ fn find_in_path_impl (
748
+ & mut self ,
749
+ path : & Path ,
750
+ requested_items : RequestedItems ,
751
+ mut in_the_middle : bool ,
752
+ ) {
753
+ if !self . includes_span ( path. span ) {
667
754
return ;
668
755
}
669
756
670
757
let after_colons = self . byte == Some ( b':' ) ;
671
758
672
- let mut idents: Vec < Ident > =
673
- path. segments . iter ( ) . map ( |segment| segment. ident . clone ( ) ) . collect ( ) ;
759
+ let mut idents: Vec < Ident > = Vec :: new ( ) ;
760
+
761
+ // Find in which ident we are in, and in which part of it
762
+ // (it could be that we are completting in the middle of an ident)
763
+ for segment in & path. segments {
764
+ let ident = & segment. ident ;
765
+
766
+ // Check if we are at the end of the ident
767
+ if self . byte_index == ident. span ( ) . end ( ) as usize {
768
+ idents. push ( ident. clone ( ) ) ;
769
+ break ;
770
+ }
771
+
772
+ // Check if we are in the middle of an ident
773
+ if self . includes_span ( ident. span ( ) ) {
774
+ // If so, take the substring and push that as the list of idents
775
+ // we'll do autocompletion for
776
+ let offset = self . byte_index - ident. span ( ) . start ( ) as usize ;
777
+ let substring = ident. 0 . contents [ 0 ..offset] . to_string ( ) ;
778
+ let ident = Ident :: new (
779
+ substring,
780
+ Span :: from ( ident. span ( ) . start ( ) ..ident. span ( ) . start ( ) + offset as u32 ) ,
781
+ ) ;
782
+ idents. push ( ident) ;
783
+ in_the_middle = true ;
784
+ break ;
785
+ }
786
+
787
+ idents. push ( ident. clone ( ) ) ;
788
+
789
+ // Stop if the cursor is right after this ident and '::'
790
+ if after_colons && self . byte_index == ident. span ( ) . end ( ) as usize + 2 {
791
+ break ;
792
+ }
793
+ }
794
+
795
+ if idents. len ( ) < path. segments . len ( ) {
796
+ in_the_middle = true ;
797
+ }
798
+
674
799
let prefix;
675
800
let at_root;
676
801
@@ -687,6 +812,21 @@ impl<'a> NodeFinder<'a> {
687
812
let is_single_segment = !after_colons && idents. is_empty ( ) && path. kind == PathKind :: Plain ;
688
813
let module_id;
689
814
815
+ let module_completion_kind = if after_colons || !idents. is_empty ( ) {
816
+ ModuleCompletionKind :: DirectChildren
817
+ } else {
818
+ ModuleCompletionKind :: AllVisibleItems
819
+ } ;
820
+
821
+ // When completing in the middle of an ident, we don't want to complete
822
+ // with function parameters because there might already be function parameters,
823
+ // and in the middle of a path it leads to code that won't compile
824
+ let function_completion_kind = if in_the_middle {
825
+ FunctionCompletionKind :: Name
826
+ } else {
827
+ FunctionCompletionKind :: NameAndParameters
828
+ } ;
829
+
690
830
if idents. is_empty ( ) {
691
831
module_id = self . module_id ;
692
832
} else {
@@ -702,6 +842,7 @@ impl<'a> NodeFinder<'a> {
702
842
& Type :: Struct ( struct_type, vec ! [ ] ) ,
703
843
& prefix,
704
844
FunctionKind :: Any ,
845
+ function_completion_kind,
705
846
) ;
706
847
return ;
707
848
}
@@ -712,25 +853,28 @@ impl<'a> NodeFinder<'a> {
712
853
ModuleDefId :: TypeAliasId ( type_alias_id) => {
713
854
let type_alias = self . interner . get_type_alias ( type_alias_id) ;
714
855
let type_alias = type_alias. borrow ( ) ;
715
- self . complete_type_methods ( & type_alias. typ , & prefix, FunctionKind :: Any ) ;
856
+ self . complete_type_methods (
857
+ & type_alias. typ ,
858
+ & prefix,
859
+ FunctionKind :: Any ,
860
+ function_completion_kind,
861
+ ) ;
716
862
return ;
717
863
}
718
864
ModuleDefId :: TraitId ( trait_id) => {
719
865
let trait_ = self . interner . get_trait ( trait_id) ;
720
- self . complete_trait_methods ( trait_, & prefix, FunctionKind :: Any ) ;
866
+ self . complete_trait_methods (
867
+ trait_,
868
+ & prefix,
869
+ FunctionKind :: Any ,
870
+ function_completion_kind,
871
+ ) ;
721
872
return ;
722
873
}
723
874
ModuleDefId :: GlobalId ( _) => return ,
724
875
}
725
876
}
726
877
727
- let module_completion_kind = if after_colons {
728
- ModuleCompletionKind :: DirectChildren
729
- } else {
730
- ModuleCompletionKind :: AllVisibleItems
731
- } ;
732
- let function_completion_kind = FunctionCompletionKind :: NameAndParameters ;
733
-
734
878
self . complete_in_module (
735
879
module_id,
736
880
& prefix,
@@ -745,15 +889,15 @@ impl<'a> NodeFinder<'a> {
745
889
match requested_items {
746
890
RequestedItems :: AnyItems => {
747
891
self . local_variables_completion ( & prefix) ;
748
- self . builtin_functions_completion ( & prefix) ;
892
+ self . builtin_functions_completion ( & prefix, function_completion_kind ) ;
749
893
self . builtin_values_completion ( & prefix) ;
750
894
}
751
895
RequestedItems :: OnlyTypes => {
752
896
self . builtin_types_completion ( & prefix) ;
753
897
self . type_parameters_completion ( & prefix) ;
754
898
}
755
899
}
756
- self . complete_auto_imports ( & prefix, requested_items) ;
900
+ self . complete_auto_imports ( & prefix, requested_items, function_completion_kind ) ;
757
901
}
758
902
}
759
903
@@ -924,17 +1068,30 @@ impl<'a> NodeFinder<'a> {
924
1068
} ;
925
1069
}
926
1070
927
- fn complete_type_fields_and_methods ( & mut self , typ : & Type , prefix : & str ) {
1071
+ fn complete_type_fields_and_methods (
1072
+ & mut self ,
1073
+ typ : & Type ,
1074
+ prefix : & str ,
1075
+ function_completion_kind : FunctionCompletionKind ,
1076
+ ) {
928
1077
match typ {
929
1078
Type :: Struct ( struct_type, generics) => {
930
1079
self . complete_struct_fields ( & struct_type. borrow ( ) , generics, prefix) ;
931
1080
}
932
1081
Type :: MutableReference ( typ) => {
933
- return self . complete_type_fields_and_methods ( typ, prefix) ;
1082
+ return self . complete_type_fields_and_methods (
1083
+ typ,
1084
+ prefix,
1085
+ function_completion_kind,
1086
+ ) ;
934
1087
}
935
1088
Type :: Alias ( type_alias, _) => {
936
1089
let type_alias = type_alias. borrow ( ) ;
937
- return self . complete_type_fields_and_methods ( & type_alias. typ , prefix) ;
1090
+ return self . complete_type_fields_and_methods (
1091
+ & type_alias. typ ,
1092
+ prefix,
1093
+ function_completion_kind,
1094
+ ) ;
938
1095
}
939
1096
Type :: Tuple ( types) => {
940
1097
self . complete_tuple_fields ( types) ;
@@ -958,10 +1115,21 @@ impl<'a> NodeFinder<'a> {
958
1115
| Type :: Error => ( ) ,
959
1116
}
960
1117
961
- self . complete_type_methods ( typ, prefix, FunctionKind :: SelfType ( typ) ) ;
1118
+ self . complete_type_methods (
1119
+ typ,
1120
+ prefix,
1121
+ FunctionKind :: SelfType ( typ) ,
1122
+ function_completion_kind,
1123
+ ) ;
962
1124
}
963
1125
964
- fn complete_type_methods ( & mut self , typ : & Type , prefix : & str , function_kind : FunctionKind ) {
1126
+ fn complete_type_methods (
1127
+ & mut self ,
1128
+ typ : & Type ,
1129
+ prefix : & str ,
1130
+ function_kind : FunctionKind ,
1131
+ function_completion_kind : FunctionCompletionKind ,
1132
+ ) {
965
1133
let Some ( methods_by_name) = self . interner . get_type_methods ( typ) else {
966
1134
return ;
967
1135
} ;
@@ -971,7 +1139,7 @@ impl<'a> NodeFinder<'a> {
971
1139
if name_matches ( name, prefix) {
972
1140
if let Some ( completion_item) = self . function_completion_item (
973
1141
func_id,
974
- FunctionCompletionKind :: NameAndParameters ,
1142
+ function_completion_kind ,
975
1143
function_kind,
976
1144
) {
977
1145
self . completion_items . push ( completion_item) ;
@@ -987,14 +1155,13 @@ impl<'a> NodeFinder<'a> {
987
1155
trait_ : & Trait ,
988
1156
prefix : & str ,
989
1157
function_kind : FunctionKind ,
1158
+ function_completion_kind : FunctionCompletionKind ,
990
1159
) {
991
1160
for ( name, func_id) in & trait_. method_ids {
992
1161
if name_matches ( name, prefix) {
993
- if let Some ( completion_item) = self . function_completion_item (
994
- * func_id,
995
- FunctionCompletionKind :: NameAndParameters ,
996
- function_kind,
997
- ) {
1162
+ if let Some ( completion_item) =
1163
+ self . function_completion_item ( * func_id, function_completion_kind, function_kind)
1164
+ {
998
1165
self . completion_items . push ( completion_item) ;
999
1166
self . suggested_module_def_ids . insert ( ModuleDefId :: FunctionId ( * func_id) ) ;
1000
1167
}
0 commit comments