@@ -59,6 +59,64 @@ export const LocationLinkSchema = z.object({
5959} )
6060export type LocationLink = z . infer < typeof LocationLinkSchema >
6161
62+ /**
63+ * Completion item kind mapping
64+ * @see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItemKind
65+ */
66+ export enum CompletionItemKind {
67+ Text = 1 ,
68+ Method = 2 ,
69+ Function = 3 ,
70+ Constructor = 4 ,
71+ Field = 5 ,
72+ Variable = 6 ,
73+ Class = 7 ,
74+ Interface = 8 ,
75+ Module = 9 ,
76+ Property = 10 ,
77+ Unit = 11 ,
78+ Value = 12 ,
79+ Enum = 13 ,
80+ Keyword = 14 ,
81+ Snippet = 15 ,
82+ Color = 16 ,
83+ File = 17 ,
84+ Reference = 18 ,
85+ Folder = 19 ,
86+ EnumMember = 20 ,
87+ Constant = 21 ,
88+ Struct = 22 ,
89+ Event = 23 ,
90+ Operator = 24 ,
91+ TypeParameter = 25 ,
92+ }
93+
94+ /**
95+ * LSP CompletionItem schema
96+ * A completion item represents a text snippet that is proposed to complete text being typed.
97+ */
98+ export const CompletionItemSchema = z . object ( {
99+ label : z . string ( ) ,
100+ kind : z . number ( ) . optional ( ) ,
101+ detail : z . string ( ) . optional ( ) ,
102+ documentation : z . union ( [ z . string ( ) , z . object ( { kind : z . string ( ) , value : z . string ( ) } ) ] ) . optional ( ) ,
103+ sortText : z . string ( ) . optional ( ) ,
104+ filterText : z . string ( ) . optional ( ) ,
105+ insertText : z . string ( ) . optional ( ) ,
106+ insertTextFormat : z . number ( ) . optional ( ) ,
107+ } )
108+ export type CompletionItem = z . infer < typeof CompletionItemSchema >
109+
110+ /**
111+ * LSP CompletionList schema
112+ * Represents a collection of completion items to be presented in the editor.
113+ */
114+ export const CompletionListSchema = z . object ( {
115+ isIncomplete : z . boolean ( ) ,
116+ items : z . array ( CompletionItemSchema ) ,
117+ } )
118+ export type CompletionList = z . infer < typeof CompletionListSchema >
119+
62120/**
63121 * LSP Symbol schema
64122 */
@@ -459,6 +517,73 @@ export class LSPManager {
459517 return results . flat ( )
460518 }
461519
520+ /**
521+ * Get code completion suggestions at the given position
522+ *
523+ * @see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion
524+ */
525+ async completion ( input : {
526+ file : string
527+ line : number
528+ character : number
529+ } ) : Promise < CompletionItem [ ] > {
530+ const clients = await this . getClients ( input . file )
531+
532+ const results = await Promise . all (
533+ clients . map ( client =>
534+ client . connection
535+ . sendRequest ( 'textDocument/completion' , {
536+ textDocument : {
537+ uri : pathToFileURL ( input . file ) . href ,
538+ } ,
539+ position : {
540+ line : input . line ,
541+ character : input . character ,
542+ } ,
543+ } )
544+ . then ( ( result : unknown ) => this . normalizeCompletions ( result ) )
545+ . catch ( ( ) => [ ] ) ,
546+ ) ,
547+ )
548+
549+ return results . flat ( )
550+ }
551+
552+ /**
553+ * Normalize completion response to CompletionItem[]
554+ * Handles CompletionList and CompletionItem[] responses
555+ */
556+ private normalizeCompletions ( result : unknown ) : CompletionItem [ ] {
557+ if ( ! result )
558+ return [ ]
559+
560+ // CompletionList format
561+ if ( this . isCompletionList ( result ) ) {
562+ return result . items
563+ }
564+
565+ // Direct CompletionItem[] format
566+ if ( Array . isArray ( result ) ) {
567+ return result . filter ( ( item ) : item is CompletionItem =>
568+ typeof item === 'object' && item !== null && 'label' in item ,
569+ )
570+ }
571+
572+ return [ ]
573+ }
574+
575+ /**
576+ * Type guard for CompletionList
577+ */
578+ private isCompletionList ( obj : unknown ) : obj is CompletionList {
579+ return (
580+ typeof obj === 'object'
581+ && obj !== null
582+ && 'items' in obj
583+ && Array . isArray ( ( obj as CompletionList ) . items )
584+ )
585+ }
586+
462587 /**
463588 * Normalize definition response to Location[]
464589 * Handles Location, Location[], and LocationLink[] responses
0 commit comments