11use serde_json:: Value ;
22
3- pub fn should_sort_completions ( msg : & Value ) -> bool {
3+ /// Returns true if the message contains a completion response with items.
4+ pub fn is_completion_response ( msg : & Value ) -> bool {
45 msg. get ( "result" ) . is_some_and ( |result| {
56 result. get ( "items" ) . is_some_and ( |v| v. is_array ( ) ) || result. is_array ( )
67 } )
78}
89
9- pub fn sort_completions_by_param_count ( msg : & mut Value ) {
10- let items = if let Some ( result) = msg. get_mut ( "result" ) {
11- if result. is_array ( ) {
12- result. as_array_mut ( )
13- } else {
14- result. get_mut ( "items" ) . and_then ( |v| v. as_array_mut ( ) )
15- }
16- } else {
17- None
10+ /// Single-pass processing of completion items:
11+ /// - Sorts methods/functions by parameter count (prepends count to sortText)
12+ /// - Strips unsupported VS Code snippet variables ($TM_SELECTED_TEXT) from snippets
13+ pub fn process_completions ( msg : & mut Value ) {
14+ let items = match msg. get_mut ( "result" ) {
15+ Some ( result) if result. is_array ( ) => result. as_array_mut ( ) ,
16+ Some ( result) => result. get_mut ( "items" ) . and_then ( |v| v. as_array_mut ( ) ) ,
17+ None => None ,
1818 } ;
1919
20- if let Some ( items) = items {
21- for item in items. iter_mut ( ) {
22- let kind = item. get ( "kind" ) . and_then ( |v| v. as_u64 ( ) ) . unwrap_or ( 0 ) ;
23- if kind == 2 || kind == 3 {
20+ let Some ( items) = items else { return } ;
21+
22+ for item in items. iter_mut ( ) {
23+ let kind = item. get ( "kind" ) . and_then ( |v| v. as_u64 ( ) ) . unwrap_or ( 0 ) ;
24+
25+ match kind {
26+ // Method (2) or Function (3): prepend param count to sortText
27+ 2 | 3 => {
2428 let detail = item
2529 . pointer ( "/labelDetails/detail" )
2630 . and_then ( |v| v. as_str ( ) )
@@ -29,29 +33,55 @@ pub fn sort_completions_by_param_count(msg: &mut Value) {
2933 let existing = item. get ( "sortText" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "" ) ;
3034 item[ "sortText" ] = Value :: String ( format ! ( "{count:02}{existing}" ) ) ;
3135 }
36+ // Snippet (15): strip $TM_SELECTED_TEXT
37+ 15 => {
38+ strip_tm_selected_text ( item, "textEditText" ) ;
39+ strip_tm_selected_text ( item, "insertText" ) ;
40+ }
41+ _ => { }
3242 }
3343 }
3444}
3545
36- fn count_params ( detail : & str ) -> usize {
37- if detail. is_empty ( ) || detail == "()" {
38- return 0 ;
46+ fn strip_tm_selected_text ( item : & mut Value , key : & str ) {
47+ if let Some ( text) = item. get ( key) . and_then ( |v| v. as_str ( ) ) {
48+ if text. contains ( "$TM_SELECTED_TEXT" ) {
49+ item[ key] = Value :: String ( text. replace ( "$TM_SELECTED_TEXT" , "" ) ) ;
50+ }
3951 }
40- let inner = detail
41- . strip_prefix ( '(' )
42- . and_then ( |s| s. strip_suffix ( ')' ) )
43- . unwrap_or ( detail)
44- . trim ( ) ;
52+ }
53+
54+ /// Sanitize a single resolved completion item (completionItem/resolve response).
55+ pub fn sanitize_resolved_completion ( msg : & mut Value ) {
56+ let Some ( result) = msg. get_mut ( "result" ) else {
57+ return ;
58+ } ;
59+ strip_tm_selected_text ( result, "textEditText" ) ;
60+ strip_tm_selected_text ( result, "insertText" ) ;
61+ // Also check inside textEdit.newText
62+ if let Some ( new_text) = result. pointer ( "/textEdit/newText" ) . and_then ( |v| v. as_str ( ) ) {
63+ if new_text. contains ( "$TM_SELECTED_TEXT" ) {
64+ result[ "textEdit" ] [ "newText" ] =
65+ Value :: String ( new_text. replace ( "$TM_SELECTED_TEXT" , "" ) ) ;
66+ }
67+ }
68+ }
69+
70+ fn count_params ( detail : & str ) -> usize {
71+ let inner = match detail. strip_prefix ( '(' ) . and_then ( |s| s. strip_suffix ( ')' ) ) {
72+ Some ( s) => s. trim ( ) ,
73+ None => return 0 ,
74+ } ;
4575 if inner. is_empty ( ) {
4676 return 0 ;
4777 }
4878 let mut count = 1usize ;
4979 let mut depth = 0i32 ;
50- for ch in inner. chars ( ) {
80+ for ch in inner. bytes ( ) {
5181 match ch {
52- '<' => depth += 1 ,
53- '>' => depth -= 1 ,
54- ',' if depth == 0 => count += 1 ,
82+ b '<' => depth += 1 ,
83+ b '>' => depth -= 1 ,
84+ b ',' if depth == 0 => count += 1 ,
5585 _ => { }
5686 }
5787 }
0 commit comments