@@ -4,8 +4,8 @@ use std::future::{self, Future};
44use async_lsp:: ResponseError ;
55use fm:: { FileId , FileMap , PathString } ;
66use lsp_types:: {
7- InlayHint , InlayHintKind , InlayHintLabel , InlayHintLabelPart , InlayHintParams , Position ,
8- TextDocumentPositionParams ,
7+ InlayHint , InlayHintKind , InlayHintLabel , InlayHintLabelPart , InlayHintParams , Position , Range ,
8+ TextDocumentPositionParams , TextEdit ,
99} ;
1010use noirc_errors:: { Location , Span } ;
1111use noirc_frontend:: {
@@ -173,7 +173,7 @@ impl<'a> InlayHintCollector<'a> {
173173 self . collect_in_expression ( & assign_statement. expression ) ;
174174 }
175175 StatementKind :: For ( for_loop_statement) => {
176- self . collect_in_ident ( & for_loop_statement. identifier ) ;
176+ self . collect_in_ident ( & for_loop_statement. identifier , false ) ;
177177 self . collect_in_expression ( & for_loop_statement. block ) ;
178178 }
179179 StatementKind :: Comptime ( statement) => self . collect_in_statement ( statement) ,
@@ -276,7 +276,7 @@ impl<'a> InlayHintCollector<'a> {
276276
277277 match pattern {
278278 Pattern :: Identifier ( ident) => {
279- self . collect_in_ident ( ident) ;
279+ self . collect_in_ident ( ident, true ) ;
280280 }
281281 Pattern :: Mutable ( pattern, _span, _is_synthesized) => {
282282 self . collect_in_pattern ( pattern) ;
@@ -294,7 +294,7 @@ impl<'a> InlayHintCollector<'a> {
294294 }
295295 }
296296
297- fn collect_in_ident ( & mut self , ident : & Ident ) {
297+ fn collect_in_ident ( & mut self , ident : & Ident , editable : bool ) {
298298 if !self . options . type_hints . enabled {
299299 return ;
300300 }
@@ -308,17 +308,17 @@ impl<'a> InlayHintCollector<'a> {
308308 let global_info = self . interner . get_global ( global_id) ;
309309 let definition_id = global_info. definition_id ;
310310 let typ = self . interner . definition_type ( definition_id) ;
311- self . push_type_hint ( lsp_location, & typ) ;
311+ self . push_type_hint ( lsp_location, & typ, editable ) ;
312312 }
313313 ReferenceId :: Local ( definition_id) => {
314314 let typ = self . interner . definition_type ( definition_id) ;
315- self . push_type_hint ( lsp_location, & typ) ;
315+ self . push_type_hint ( lsp_location, & typ, editable ) ;
316316 }
317317 ReferenceId :: StructMember ( struct_id, field_index) => {
318318 let struct_type = self . interner . get_struct ( struct_id) ;
319319 let struct_type = struct_type. borrow ( ) ;
320320 let ( _field_name, field_type) = struct_type. field_at ( field_index) ;
321- self . push_type_hint ( lsp_location, field_type) ;
321+ self . push_type_hint ( lsp_location, field_type, false ) ;
322322 }
323323 ReferenceId :: Module ( _)
324324 | ReferenceId :: Struct ( _)
@@ -331,7 +331,7 @@ impl<'a> InlayHintCollector<'a> {
331331 }
332332 }
333333
334- fn push_type_hint ( & mut self , location : lsp_types:: Location , typ : & Type ) {
334+ fn push_type_hint ( & mut self , location : lsp_types:: Location , typ : & Type , editable : bool ) {
335335 let position = location. range . end ;
336336
337337 let mut parts = Vec :: new ( ) ;
@@ -342,7 +342,14 @@ impl<'a> InlayHintCollector<'a> {
342342 position,
343343 label : InlayHintLabel :: LabelParts ( parts) ,
344344 kind : Some ( InlayHintKind :: TYPE ) ,
345- text_edits : None ,
345+ text_edits : if editable {
346+ Some ( vec ! [ TextEdit {
347+ range: Range { start: location. range. end, end: location. range. end } ,
348+ new_text: format!( ": {}" , typ) ,
349+ } ] )
350+ } else {
351+ None
352+ } ,
346353 tooltip : None ,
347354 padding_left : None ,
348355 padding_right : None ,
@@ -756,8 +763,10 @@ mod inlay_hints_tests {
756763 let inlay_hints = get_inlay_hints ( 0 , 3 , type_hints ( ) ) . await ;
757764 assert_eq ! ( inlay_hints. len( ) , 1 ) ;
758765
766+ let position = Position { line : 1 , character : 11 } ;
767+
759768 let inlay_hint = & inlay_hints[ 0 ] ;
760- assert_eq ! ( inlay_hint. position, Position { line : 1 , character : 11 } ) ;
769+ assert_eq ! ( inlay_hint. position, position ) ;
761770
762771 if let InlayHintLabel :: LabelParts ( labels) = & inlay_hint. label {
763772 assert_eq ! ( labels. len( ) , 2 ) ;
@@ -770,15 +779,25 @@ mod inlay_hints_tests {
770779 } else {
771780 panic ! ( "Expected InlayHintLabel::LabelParts, got {:?}" , inlay_hint. label) ;
772781 }
782+
783+ assert_eq ! (
784+ inlay_hint. text_edits,
785+ Some ( vec![ TextEdit {
786+ range: Range { start: position, end: position } ,
787+ new_text: ": Field" . to_string( ) ,
788+ } ] )
789+ ) ;
773790 }
774791
775792 #[ test]
776793 async fn test_type_inlay_hints_with_location ( ) {
777794 let inlay_hints = get_inlay_hints ( 12 , 15 , type_hints ( ) ) . await ;
778795 assert_eq ! ( inlay_hints. len( ) , 1 ) ;
779796
797+ let position = Position { line : 13 , character : 11 } ;
798+
780799 let inlay_hint = & inlay_hints[ 0 ] ;
781- assert_eq ! ( inlay_hint. position, Position { line : 13 , character : 11 } ) ;
800+ assert_eq ! ( inlay_hint. position, position ) ;
782801
783802 if let InlayHintLabel :: LabelParts ( labels) = & inlay_hint. label {
784803 assert_eq ! ( labels. len( ) , 2 ) ;
@@ -798,6 +817,34 @@ mod inlay_hints_tests {
798817 } else {
799818 panic ! ( "Expected InlayHintLabel::LabelParts, got {:?}" , inlay_hint. label) ;
800819 }
820+
821+ assert_eq ! (
822+ inlay_hint. text_edits,
823+ Some ( vec![ TextEdit {
824+ range: Range { start: position, end: position } ,
825+ new_text: ": Foo" . to_string( ) ,
826+ } ] )
827+ ) ;
828+ }
829+
830+ #[ test]
831+ async fn test_type_inlay_hints_in_struct_member_pattern ( ) {
832+ let inlay_hints = get_inlay_hints ( 94 , 96 , type_hints ( ) ) . await ;
833+ assert_eq ! ( inlay_hints. len( ) , 1 ) ;
834+
835+ let inlay_hint = & inlay_hints[ 0 ] ;
836+ assert_eq ! ( inlay_hint. position, Position { line: 95 , character: 24 } ) ;
837+
838+ if let InlayHintLabel :: LabelParts ( labels) = & inlay_hint. label {
839+ assert_eq ! ( labels. len( ) , 2 ) ;
840+ assert_eq ! ( labels[ 0 ] . value, ": " ) ;
841+ assert_eq ! ( labels[ 0 ] . location, None ) ;
842+ assert_eq ! ( labels[ 1 ] . value, "i32" ) ;
843+ } else {
844+ panic ! ( "Expected InlayHintLabel::LabelParts, got {:?}" , inlay_hint. label) ;
845+ }
846+
847+ assert_eq ! ( inlay_hint. text_edits, None ) ;
801848 }
802849
803850 #[ test]
@@ -816,15 +863,19 @@ mod inlay_hints_tests {
816863 } else {
817864 panic ! ( "Expected InlayHintLabel::LabelParts, got {:?}" , inlay_hint. label) ;
818865 }
866+
867+ assert_eq ! ( inlay_hint. text_edits, None ) ;
819868 }
820869
821870 #[ test]
822871 async fn test_type_inlay_hints_in_global ( ) {
823872 let inlay_hints = get_inlay_hints ( 19 , 21 , type_hints ( ) ) . await ;
824873 assert_eq ! ( inlay_hints. len( ) , 1 ) ;
825874
875+ let position = Position { line : 20 , character : 10 } ;
876+
826877 let inlay_hint = & inlay_hints[ 0 ] ;
827- assert_eq ! ( inlay_hint. position, Position { line : 20 , character : 10 } ) ;
878+ assert_eq ! ( inlay_hint. position, position ) ;
828879
829880 if let InlayHintLabel :: LabelParts ( labels) = & inlay_hint. label {
830881 assert_eq ! ( labels. len( ) , 2 ) ;
@@ -834,6 +885,14 @@ mod inlay_hints_tests {
834885 } else {
835886 panic ! ( "Expected InlayHintLabel::LabelParts, got {:?}" , inlay_hint. label) ;
836887 }
888+
889+ assert_eq ! (
890+ inlay_hint. text_edits,
891+ Some ( vec![ TextEdit {
892+ range: Range { start: position, end: position } ,
893+ new_text: ": Field" . to_string( ) ,
894+ } ] )
895+ ) ;
837896 }
838897
839898 #[ test]
@@ -855,6 +914,7 @@ mod inlay_hints_tests {
855914
856915 let inlay_hint = & inlay_hints[ 0 ] ;
857916 assert_eq ! ( inlay_hint. position, Position { line: 25 , character: 12 } ) ;
917+ assert_eq ! ( inlay_hint. text_edits, None ) ;
858918 if let InlayHintLabel :: String ( label) = & inlay_hint. label {
859919 assert_eq ! ( label, "one: " ) ;
860920 } else {
@@ -863,6 +923,7 @@ mod inlay_hints_tests {
863923
864924 let inlay_hint = & inlay_hints[ 1 ] ;
865925 assert_eq ! ( inlay_hint. position, Position { line: 25 , character: 15 } ) ;
926+ assert_eq ! ( inlay_hint. text_edits, None ) ;
866927 if let InlayHintLabel :: String ( label) = & inlay_hint. label {
867928 assert_eq ! ( label, "two: " ) ;
868929 } else {
@@ -877,6 +938,7 @@ mod inlay_hints_tests {
877938
878939 let inlay_hint = & inlay_hints[ 0 ] ;
879940 assert_eq ! ( inlay_hint. position, Position { line: 38 , character: 18 } ) ;
941+ assert_eq ! ( inlay_hint. text_edits, None ) ;
880942 if let InlayHintLabel :: String ( label) = & inlay_hint. label {
881943 assert_eq ! ( label, "one: " ) ;
882944 } else {
0 commit comments