@@ -17,6 +17,9 @@ import { Connection } from "vscode-languageserver";
1717import {
1818 TextDocumentPositionParams ,
1919 DocumentFormattingParams ,
20+ DocumentSymbolParams ,
21+ DocumentSymbol ,
22+ SymbolInformation ,
2023} from "vscode-languageserver-protocol" ;
2124import { CompletionList , TextEdit , Hover } from "vscode-languageserver-types" ;
2225import { SettingsState } from "../../cfnSettings" ;
@@ -31,11 +34,14 @@ import {
3134} from "yaml-language-server/out/server/src/languageservice/parser/jsonParser07" ;
3235import { MarkdownString } from "../../utils/markdownString" ;
3336import { LanguageService } from "../../service/cfnLanguageService" ;
37+ import { ResultLimitReachedNotification } from "../../requestTypes" ;
38+ import * as path from "path" ;
3439
3540// code adopted from https://github.com/redhat-developer/yaml-language-server/blob/main/src/languageserver/handlers/languageHandlers.ts
3641export class LanguageHandlers extends YamlLanguageHandlers {
3742 private cfnLanguageService : LanguageService ;
3843 private cfnSettings : SettingsState ;
44+ private cfnConnection : Connection ;
3945
4046 pendingLimitExceededWarnings : {
4147 [ uri : string ] : {
@@ -51,6 +57,7 @@ export class LanguageHandlers extends YamlLanguageHandlers {
5157 validationHandler : ValidationHandler
5258 ) {
5359 super ( connection , languageService , cfnSettings , validationHandler ) ;
60+ this . cfnConnection = connection ;
5461 this . cfnSettings = cfnSettings ;
5562 this . cfnLanguageService = languageService ;
5663 }
@@ -75,14 +82,18 @@ export class LanguageHandlers extends YamlLanguageHandlers {
7582 return Promise . resolve ( result ) ;
7683 }
7784
85+ let [ node , template ] = getNode ( textDocument , textDocumentPosition ) ;
86+
87+ if ( ! template . isValidTemplate && textDocument . lineCount > 4 ) {
88+ return Promise . resolve ( result ) ;
89+ }
90+
7891 const results = await this . cfnLanguageService . doComplete (
7992 textDocument ,
8093 textDocumentPosition . position ,
8194 false
8295 ) ;
8396
84- let [ node , template ] = getNode ( textDocument , textDocumentPosition ) ;
85-
8697 function addResources ( prefix : string ) {
8798 template . resources . forEach ( ( value : TypeInfoImpl , key : string ) => {
8899 results . items . push ( {
@@ -173,6 +184,53 @@ export class LanguageHandlers extends YamlLanguageHandlers {
173184 return this . cfnLanguageService . doFormat ( document , customFormatterSettings ) ;
174185 }
175186
187+ /**
188+ * Called when the code outline in an editor needs to be populated
189+ * Returns a list of symbols that is then shown in the code outline
190+ */
191+ documentSymbolHandler (
192+ documentSymbolParams : DocumentSymbolParams
193+ ) : DocumentSymbol [ ] | SymbolInformation [ ] {
194+ const document = this . cfnSettings . documents . get (
195+ documentSymbolParams . textDocument . uri
196+ ) ;
197+
198+ if ( ! document ) {
199+ // @ts -ignore
200+ return ;
201+ }
202+
203+ let [ _ , template ] = getNode ( document , {
204+ textDocument : document ,
205+ position : {
206+ line : 0 ,
207+ character : 0 ,
208+ } ,
209+ } ) ;
210+
211+ if ( ! template . isValidTemplate ) {
212+ // @ts -ignore
213+ return ;
214+ }
215+
216+ const onResultLimitExceeded = this . onCfnResultLimitExceeded (
217+ document . uri ,
218+ this . cfnSettings . maxItemsComputed ,
219+ "document symbols"
220+ ) ;
221+
222+ const context = {
223+ resultLimit : this . cfnSettings . maxItemsComputed ,
224+ onResultLimitExceeded,
225+ } ;
226+
227+ if ( this . cfnSettings . hierarchicalDocumentSymbolSupport ) {
228+ return this . cfnLanguageService . findDocumentSymbols2 ( document , context ) ;
229+ } else {
230+ return this . cfnLanguageService . findDocumentSymbols ( document , context ) ;
231+ }
232+ }
233+
176234 /**
177235 * Called when the user hovers with their mouse over a keyword
178236 * Returns an informational tooltip
@@ -240,4 +298,34 @@ export class LanguageHandlers extends YamlLanguageHandlers {
240298
241299 return hover ;
242300 }
301+
302+ private onCfnResultLimitExceeded (
303+ uri : string ,
304+ resultLimit : number ,
305+ name : string
306+ ) {
307+ return ( ) => {
308+ let warning = this . pendingLimitExceededWarnings [ uri ] ;
309+ if ( warning ) {
310+ if ( ! warning . timeout ) {
311+ // already shown
312+ return ;
313+ }
314+ warning . features [ name ] = name ;
315+ warning . timeout . refresh ( ) ;
316+ } else {
317+ warning = { features : { [ name ] : name } } ;
318+ warning . timeout = setTimeout ( ( ) => {
319+ this . cfnConnection . sendNotification (
320+ ResultLimitReachedNotification . type ,
321+ `${ path . basename ( uri ) } : For performance reasons, ${ Object . keys (
322+ warning . features
323+ ) . join ( " and " ) } have been limited to ${ resultLimit } items.`
324+ ) ;
325+ warning . timeout = undefined ;
326+ } , 2000 ) ;
327+ this . pendingLimitExceededWarnings [ uri ] = warning ;
328+ }
329+ } ;
330+ }
243331}
0 commit comments