@@ -7,8 +7,10 @@ import {
77 CompletionItem ,
88 CompletionItemKind ,
99 TextDocumentPositionParams ,
10+ TextDocumentPositionParams ,
1011 TextDocumentSyncKind ,
11- InitializeResult
12+ InitializeResult ,
13+ Location
1214} from 'vscode-languageserver/node' ;
1315import {
1416 TextDocument
@@ -48,7 +50,8 @@ connection.onInitialize((params: InitializeParams) => {
4850 // Tell the client that this server supports code completion.
4951 completionProvider : {
5052 resolveProvider : true
51- }
53+ } ,
54+ definitionProvider : true
5255 }
5356 } ;
5457 if ( hasWorkspaceFolderCapability ) {
@@ -81,7 +84,7 @@ documents.onDidChangeContent(_change => {
8184
8285connection . onDidChangeWatchedFiles ( _change => {
8386 // Monitored files have change in VSCode
84- connection . console . log ( 'We received an file change event' ) ;
87+ connection . console . log ( 'We received an file change event' ) ;
8588} ) ;
8689
8790// This handler provides the initial list of the completion items.
@@ -90,31 +93,31 @@ connection.onCompletion(
9093 // The pass parameter contains the position of the text document in
9194 // which code complete got requested. For the example we ignore this
9295 // info and always provide the same completion items.
93-
94- const keywords = [
95- 'func' , 'class' , 'if' , 'else' , 'while' , 'for' , 'return' , 'print' ,
96- 'var' , 'let' , 'const' , 'true' , 'false' , 'null' , 'use' , 'export' ,
97- 'prox' , 'loop' , 'from' , 'as' , 'try' , 'catch' , 'throw' , 'async' , 'await'
98- ] ;
99- const builtins = [ 'len' , 'str' , 'clock' , 'input' , 'type' ] ;
100-
101- const items : CompletionItem [ ] = [ ] ;
102-
103- for ( const word of keywords ) {
104- items . push ( {
105- label : word ,
106- kind : CompletionItemKind . Keyword ,
107- data : 1
108- } ) ;
109- }
110-
111- for ( const word of builtins ) {
112- items . push ( {
113- label : word ,
114- kind : CompletionItemKind . Function ,
115- data : 2
116- } ) ;
117- }
96+
97+ const keywords = [
98+ 'func' , 'class' , 'if' , 'else' , 'while' , 'for' , 'return' , 'print' ,
99+ 'var' , 'let' , 'const' , 'true' , 'false' , 'null' , 'use' , 'export' ,
100+ 'prox' , 'loop' , 'from' , 'as' , 'try' , 'catch' , 'throw' , 'async' , 'await'
101+ ] ;
102+ const builtins = [ 'len' , 'str' , 'clock' , 'input' , 'type' ] ;
103+
104+ const items : CompletionItem [ ] = [ ] ;
105+
106+ for ( const word of keywords ) {
107+ items . push ( {
108+ label : word ,
109+ kind : CompletionItemKind . Keyword ,
110+ data : 1
111+ } ) ;
112+ }
113+
114+ for ( const word of builtins ) {
115+ items . push ( {
116+ label : word ,
117+ kind : CompletionItemKind . Function ,
118+ data : 2
119+ } ) ;
120+ }
118121
119122 return items ;
120123 }
@@ -135,6 +138,60 @@ connection.onCompletionResolve(
135138 }
136139) ;
137140
141+ connection . onDefinition (
142+ ( params : TextDocumentPositionParams ) : Location | null => {
143+ const document = documents . get ( params . textDocument . uri ) ;
144+ if ( ! document ) return null ;
145+
146+ const position = params . position ;
147+ const offset = document . offsetAt ( position ) ;
148+ const text = document . getText ( ) ;
149+
150+ // Simple word extraction
151+ const wordRegex = / [ a - z A - Z 0 - 9 _ ] + / g;
152+ let match ;
153+ let word = "" ;
154+
155+ while ( ( match = wordRegex . exec ( text ) ) !== null ) {
156+ if ( offset >= match . index && offset <= match . index + match [ 0 ] . length ) {
157+ word = match [ 0 ] ;
158+ break ;
159+ }
160+ }
161+
162+ if ( ! word ) return null ;
163+
164+ // Regex to find definition
165+ // func <word> or class <word>
166+ const funcRegex = new RegExp ( `func\\s+${ word } \\s*\\(` , 'g' ) ;
167+ const classRegex = new RegExp ( `class\\s+${ word } \\s*\\{` , 'g' ) ;
168+
169+ let defMatch ;
170+ // Check functions
171+ while ( ( defMatch = funcRegex . exec ( text ) ) !== null ) {
172+ return Location . create (
173+ params . textDocument . uri ,
174+ {
175+ start : document . positionAt ( defMatch . index ) ,
176+ end : document . positionAt ( defMatch . index + match [ 0 ] . length + 5 )
177+ }
178+ ) ;
179+ }
180+ // Check classes
181+ while ( ( defMatch = classRegex . exec ( text ) ) !== null ) {
182+ return Location . create (
183+ params . textDocument . uri ,
184+ {
185+ start : document . positionAt ( defMatch . index ) ,
186+ end : document . positionAt ( defMatch . index + match [ 0 ] . length + 6 )
187+ }
188+ ) ;
189+ }
190+
191+ return null ;
192+ }
193+ ) ;
194+
138195// Make the text document manager listen on the connection
139196// for open, change and close text document events
140197documents . listen ( connection ) ;
0 commit comments