@@ -30,7 +30,9 @@ import {
3030 type CompletionContext ,
3131 type CompletionItem ,
3232 InsertTextFormat ,
33- CompletionItemKind
33+ CompletionItemKind ,
34+ type IAPIReferenceProvider ,
35+ type APIReferenceContext
3436} from './ui/code-editor-ui'
3537import {
3638 type Action ,
@@ -57,11 +59,66 @@ import {
5759 makeBasicMarkdownString ,
5860 type WorkspaceDiagnostics ,
5961 type TextDocumentDiagnostics ,
60- fromLSPDiagnostic
62+ fromLSPDiagnostic ,
63+ isTextDocumentStageCode
6164} from './common'
6265import { TextDocument , createTextDocument } from './text-document'
6366import { type Monaco } from './monaco'
6467
68+ class APIReferenceProvider implements IAPIReferenceProvider {
69+ constructor (
70+ private documentBase : DocumentBase ,
71+ private lspClient : SpxLSPClient
72+ ) { }
73+
74+ private async getFallbackItems ( ctx : APIReferenceContext ) {
75+ const isStage = isTextDocumentStageCode ( ctx . textDocument . id )
76+ const allItems = await this . documentBase . getAllDocumentations ( )
77+ const overviewSet = new Set < string > ( )
78+ const fallbackItems : DefinitionDocumentationItem [ ] = [ ]
79+ for ( const item of allItems ) {
80+ if ( item . hiddenFromList ) continue
81+ if ( item . definition . package === packageSpx ) {
82+ const namespace = ( item . definition . name ?? '' ) . split ( '.' ) [ 0 ] // `Sprite` / `Game`
83+ if ( isStage && namespace === 'Sprite' ) continue
84+ }
85+ if ( overviewSet . has ( item . overview ) ) continue // Skip duplicated items, e.g., `Sprite.onStart` & `Game.onStart`
86+ overviewSet . add ( item . overview )
87+ fallbackItems . push ( item )
88+ }
89+ return fallbackItems
90+ }
91+
92+ async provideAPIReference ( ctx : APIReferenceContext , position : Position | null ) {
93+ if ( position == null ) return this . getFallbackItems ( ctx )
94+
95+ const definitions = await this . lspClient
96+ . workspaceExecuteCommandSpxGetDefinitions ( {
97+ textDocument : ctx . textDocument . id ,
98+ position : toLSPPosition ( position )
99+ } )
100+ . catch ( ( e ) => {
101+ console . warn ( 'Failed to get definitions' , e )
102+ return null
103+ } )
104+ ctx . signal . throwIfAborted ( )
105+ let apiReferenceItems : DefinitionDocumentationItem [ ]
106+ if ( definitions != null && definitions . length > 0 ) {
107+ const maybeDocumentationItems = await Promise . all (
108+ definitions . map ( async ( def ) => {
109+ const doc = await this . documentBase . getDocumentation ( def )
110+ if ( doc == null || doc . hiddenFromList ) return null
111+ return doc
112+ } )
113+ )
114+ apiReferenceItems = maybeDocumentationItems . filter ( ( d ) => d != null ) as DefinitionDocumentationItem [ ]
115+ } else {
116+ apiReferenceItems = await this . getFallbackItems ( ctx )
117+ }
118+ return apiReferenceItems
119+ }
120+ }
121+
65122class ResourceReferencesProvider implements IResourceReferencesProvider {
66123 constructor ( private lspClient : SpxLSPClient ) { }
67124 async provideResourceReferences ( ctx : ResourceReferencesContext ) : Promise < ResourceReference [ ] > {
@@ -388,6 +445,9 @@ export class CodeEditor extends Disposable {
388445 private copilot : Copilot
389446 private documentBase : DocumentBase
390447 private lspClient : SpxLSPClient
448+ private apiReferenceProvider : APIReferenceProvider
449+ private completionProvider : CompletionProvider
450+ private contextMenuProvider : ContextMenuProvider
391451 private resourceReferencesProvider : ResourceReferencesProvider
392452 private diagnosticsProvider : DiagnosticsProvider
393453 private hoverProvider : HoverProvider
@@ -402,6 +462,9 @@ export class CodeEditor extends Disposable {
402462 this . copilot = new Copilot ( i18n , project )
403463 this . documentBase = new DocumentBase ( )
404464 this . lspClient = new SpxLSPClient ( project )
465+ this . apiReferenceProvider = new APIReferenceProvider ( this . documentBase , this . lspClient )
466+ this . completionProvider = new CompletionProvider ( this . lspClient , this . documentBase )
467+ this . contextMenuProvider = new ContextMenuProvider ( this . lspClient , this . documentBase )
405468 this . resourceReferencesProvider = new ResourceReferencesProvider ( this . lspClient )
406469 this . diagnosticsProvider = new DiagnosticsProvider ( this . runtime , this . lspClient )
407470 this . hoverProvider = new HoverProvider ( this . lspClient , this . documentBase )
@@ -497,46 +560,15 @@ export class CodeEditor extends Disposable {
497560 const idx = this . uis . indexOf ( ui )
498561 if ( idx >= 0 ) this . uis . splice ( idx , 1 )
499562 this . uis . push ( ui )
500- ; ( window as any ) . ui = ui // for debugging only
501- const { copilot, documentBase, lspClient } = this
502-
503- ui . registerAPIReferenceProvider ( {
504- async provideAPIReference ( ctx , position ) {
505- const definitions = await lspClient
506- . workspaceExecuteCommandSpxGetDefinitions ( {
507- textDocument : ctx . textDocument . id ,
508- position : toLSPPosition ( position )
509- } )
510- . catch ( ( e ) => {
511- console . warn ( 'Failed to get definitions' , e )
512- return null
513- } )
514- ctx . signal . throwIfAborted ( )
515- let apiReferenceItems : DefinitionDocumentationItem [ ]
516- if ( definitions != null && definitions . length > 0 ) {
517- const maybeDocumentationItems = await Promise . all (
518- definitions . map ( async ( def ) => {
519- const doc = await documentBase . getDocumentation ( def )
520- if ( doc == null || doc . hiddenFromList ) return null
521- return doc
522- } )
523- )
524- apiReferenceItems = maybeDocumentationItems . filter ( ( d ) => d != null ) as DefinitionDocumentationItem [ ]
525- } else {
526- // When compiling errors encountered, we fallback to "all items".
527- apiReferenceItems = await documentBase . getAllDocumentations ( )
528- }
529- return apiReferenceItems
530- }
531- } )
532563
533- ui . registerCompletionProvider ( new CompletionProvider ( this . lspClient , documentBase ) )
534- ui . registerContextMenuProvider ( new ContextMenuProvider ( lspClient , documentBase ) )
535- ui . registerCopilot ( copilot )
564+ ui . registerAPIReferenceProvider ( this . apiReferenceProvider )
565+ ui . registerCompletionProvider ( this . completionProvider )
566+ ui . registerContextMenuProvider ( this . contextMenuProvider )
567+ ui . registerCopilot ( this . copilot )
536568 ui . registerDiagnosticsProvider ( this . diagnosticsProvider )
537569 ui . registerHoverProvider ( this . hoverProvider )
538570 ui . registerResourceReferencesProvider ( this . resourceReferencesProvider )
539- ui . registerDocumentBase ( documentBase )
571+ ui . registerDocumentBase ( this . documentBase )
540572 }
541573
542574 detachUI ( ui : ICodeEditorUI ) {
0 commit comments