11import * as vscode from "vscode" ;
22
33import { localize } from "vs/nls" ;
4- import { Action } from "vs/base/common/actions" ;
5- import { SyncActionDescriptor , MenuRegistry , MenuId } from "vs/platform/actions/common/actions" ;
4+ import { SyncActionDescriptor } from "vs/platform/actions/common/actions" ;
65import { Registry } from "vs/platform/registry/common/platform" ;
76import { IWorkbenchActionRegistry , Extensions as ActionExtensions } from "vs/workbench/common/actions" ;
87import { CommandsRegistry , ICommandService } from "vs/platform/commands/common/commands" ;
9- import { IStat , IWatchOptions , FileOverwriteOptions , FileDeleteOptions , FileOpenOptions , IFileChange , FileWriteOptions , FileSystemProviderCapabilities , IFileService , FileType , FileOperation , IFileSystemProvider } from "vs/platform/files/common/files" ;
10- import { ITextFileService } from "vs/workbench/services/textfile/common/textfiles" ;
11- import { IModelService } from "vs/editor/common/services/modelService" ;
12- import { ITerminalService } from "vs/workbench/contrib/terminal/common/terminal" ;
8+ import { IStat , IWatchOptions , FileOverwriteOptions , FileDeleteOptions , FileOpenOptions , IFileChange , FileWriteOptions , FileSystemProviderCapabilities , IFileService , FileType , IFileSystemProvider } from "vs/platform/files/common/files" ;
139import { IStorageService } from "vs/platform/storage/common/storage" ;
1410import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection" ;
1511import { INotificationService } from "vs/platform/notification/common/notification" ;
16- import { IStatusbarService , StatusbarAlignment } from "vs/platform/statusbar/common/statusbar" ;
17- import Severity from "vs/base/common/severity" ;
1812import { Emitter , Event } from "vs/base/common/event" ;
1913import * as extHostTypes from "vs/workbench/api/common/extHostTypes" ;
2014import { ServiceIdentifier , IInstantiationService } from "vs/platform/instantiation/common/instantiation" ;
2115import { URI } from "vs/base/common/uri" ;
22- import { ITreeViewDataProvider , IViewsRegistry , ITreeViewDescriptor , Extensions as ViewsExtensions , IViewContainersRegistry } from "vs/workbench/common/views" ;
16+ import { ITreeItem , ITreeViewDataProvider , IViewsRegistry , ITreeViewDescriptor , Extensions as ViewsExtensions , IViewContainersRegistry , TreeItemCollapsibleState } from "vs/workbench/common/views" ;
2317import { CustomTreeViewPanel , CustomTreeView } from "vs/workbench/browser/parts/views/customView" ;
2418import { ViewletRegistry , Extensions as ViewletExtensions , ViewletDescriptor , ShowViewletAction } from "vs/workbench/browser/viewlet" ;
2519import { IExtensionService } from "vs/workbench/services/extensions/common/extensions" ;
@@ -35,14 +29,15 @@ import { IViewletService } from "vs/workbench/services/viewlet/browser/viewlet";
3529import { IEditorGroupsService } from "vs/workbench/services/editor/common/editorGroupsService" ;
3630import { createCSSRule } from "vs/base/browser/dom" ;
3731import { IDisposable } from "vs/base/common/lifecycle" ;
32+ import { generateUuid } from "vs/base/common/uuid" ;
3833
3934/**
4035 * Client-side implementation of VS Code's API.
4136 * TODO: Views aren't quite working.
4237 * TODO: Implement menu items for views (for item actions).
4338 * TODO: File system provider doesn't work.
4439 */
45- export const vscodeApi = ( serviceCollection : ServiceCollection ) : typeof vscode => {
40+ export const vscodeApi = ( serviceCollection : ServiceCollection ) : Partial < typeof vscode > => {
4641 const getService = < T > ( id : ServiceIdentifier < T > ) : T => serviceCollection . get < T > ( id ) as T ;
4742 const commandService = getService ( ICommandService ) ;
4843 const notificationService = getService ( INotificationService ) ;
@@ -61,149 +56,84 @@ export const vscodeApi = (serviceCollection: ServiceCollection): typeof vscode =
6156 FileType : FileType ,
6257 Uri : URI ,
6358 commands : {
64- executeCommand : ( commandId : string , ...args : any [ ] ) : any => {
59+ executeCommand : < T = any > ( commandId : string , ...args : any [ ] ) : Promise < T | undefined > => {
6560 return commandService . executeCommand ( commandId , ...args ) ;
6661 } ,
67- registerCommand : ( id : string , command : ( ) => void ) : any => {
62+ registerCommand : ( id : string , command : ( ... args : any [ ] ) => any ) : IDisposable => {
6863 return CommandsRegistry . registerCommand ( id , command ) ;
6964 } ,
70- } ,
65+ } as Partial < typeof vscode . commands > ,
7166 window : {
72- registerTreeDataProvider : ( id : string , dataProvider : ITreeViewDataProvider ) : void => {
67+ registerTreeDataProvider : < T > ( id : string , dataProvider : vscode . TreeDataProvider < T > ) : IDisposable => {
68+ const tree = new TreeViewDataProvider ( dataProvider ) ;
7369 const view = viewsRegistry . getView ( id ) ;
74- if ( view ) {
75- ( view as ITreeViewDescriptor ) . treeView . dataProvider = dataProvider ;
76- }
70+ ( view as ITreeViewDescriptor ) . treeView . dataProvider = tree ;
71+ return {
72+ dispose : ( ) => tree . dispose ( ) ,
73+ } ;
7774 } ,
78- showErrorMessage : ( message : string ) : void => {
75+ showErrorMessage : async ( message : string ) : Promise < string | undefined > => {
7976 notificationService . error ( message ) ;
77+ return undefined ;
8078 } ,
81- } ,
79+ } as Partial < typeof vscode . window > ,
8280 workspace : {
8381 registerFileSystemProvider : ( scheme : string , provider : vscode . FileSystemProvider ) : IDisposable => {
8482 return fileService . registerProvider ( scheme , new FileSystemProvider ( provider ) ) ;
8583 } ,
86- } ,
87- } as any ;
84+ } as Partial < typeof vscode . workspace > ,
85+ } as Partial < typeof vscode > ; // Without this it complains that the type isn't `| undefined`.
8886} ;
8987
9088/**
91- * Coder API.
89+ * Coder API. This should only provide functionality that can't be made
90+ * available through the VS Code API.
9291 */
9392export const coderApi = ( serviceCollection : ServiceCollection ) : typeof coder => {
9493 const getService = < T > ( id : ServiceIdentifier < T > ) : T => serviceCollection . get < T > ( id ) as T ;
9594 return {
96- workbench : {
97- action : Action ,
98- syncActionDescriptor : SyncActionDescriptor ,
99- commandRegistry : CommandsRegistry ,
100- actionsRegistry : Registry . as < IWorkbenchActionRegistry > ( ActionExtensions . WorkbenchActions ) ,
101- registerView : ( viewId , viewName , containerId , containerName , icon ) : void => {
102- const cssClass = `extensionViewlet-${ containerId } ` ;
103- const id = `workbench.view.extension.${ containerId } ` ;
104- class CustomViewlet extends ViewContainerViewlet {
105- public constructor (
106- @IConfigurationService configurationService : IConfigurationService ,
107- @IWorkbenchLayoutService layoutService : IWorkbenchLayoutService ,
108- @ITelemetryService telemetryService : ITelemetryService ,
109- @IWorkspaceContextService contextService : IWorkspaceContextService ,
110- @IStorageService storageService : IStorageService ,
111- @IEditorService _editorService : IEditorService ,
112- @IInstantiationService instantiationService : IInstantiationService ,
113- @IThemeService themeService : IThemeService ,
114- @IContextMenuService contextMenuService : IContextMenuService ,
115- @IExtensionService extensionService : IExtensionService ,
116- ) {
117- super ( id , `${ id } .state` , true , configurationService , layoutService , telemetryService , storageService , instantiationService , themeService , contextMenuService , extensionService , contextService ) ;
118- }
95+ registerView : ( viewId , viewName , containerId , containerName , icon ) : void => {
96+ const cssClass = `extensionViewlet-${ containerId } ` ;
97+ const id = `workbench.view.extension.${ containerId } ` ;
98+ class CustomViewlet extends ViewContainerViewlet {
99+ public constructor (
100+ @IConfigurationService configurationService : IConfigurationService ,
101+ @IWorkbenchLayoutService layoutService : IWorkbenchLayoutService ,
102+ @ITelemetryService telemetryService : ITelemetryService ,
103+ @IWorkspaceContextService contextService : IWorkspaceContextService ,
104+ @IStorageService storageService : IStorageService ,
105+ @IEditorService _editorService : IEditorService ,
106+ @IInstantiationService instantiationService : IInstantiationService ,
107+ @IThemeService themeService : IThemeService ,
108+ @IContextMenuService contextMenuService : IContextMenuService ,
109+ @IExtensionService extensionService : IExtensionService ,
110+ ) {
111+ super ( id , `${ id } .state` , true , configurationService , layoutService , telemetryService , storageService , instantiationService , themeService , contextMenuService , extensionService , contextService ) ;
119112 }
113+ }
120114
121- Registry . as < ViewletRegistry > ( ViewletExtensions . Viewlets ) . registerViewlet (
122- new ViewletDescriptor ( CustomViewlet as any , id , containerName , cssClass , undefined , URI . parse ( icon ) ) ,
123- ) ;
124-
125- Registry . as < IWorkbenchActionRegistry > ( ActionExtensions . WorkbenchActions ) . registerWorkbenchAction (
126- new SyncActionDescriptor ( OpenCustomViewletAction as any , id , localize ( "showViewlet" , "Show {0}" , containerName ) ) ,
127- "View: Show {0}" ,
128- localize ( "view" , "View" ) ,
129- ) ;
130-
131- // Generate CSS to show the icon in the activity bar.
132- const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${ cssClass } ` ;
133- createCSSRule ( iconClass , `-webkit-mask: url('${ icon } ') no-repeat 50% 50%` ) ;
134-
135- const container = Registry . as < IViewContainersRegistry > ( ViewsExtensions . ViewContainersRegistry ) . registerViewContainer ( containerId ) ;
136- Registry . as < IViewsRegistry > ( ViewsExtensions . ViewsRegistry ) . registerViews ( [ {
137- id : viewId ,
138- name : viewName ,
139- ctorDescriptor : { ctor : CustomTreeViewPanel } ,
140- treeView : getService ( IInstantiationService ) . createInstance ( CustomTreeView as any , viewId , container ) ,
141- } ] as ITreeViewDescriptor [ ] , container ) ;
142- } ,
143- menuRegistry : MenuRegistry as any ,
144- statusbarService : getService ( IStatusbarService ) as any ,
145- notificationService : getService ( INotificationService ) ,
146- terminalService : getService ( ITerminalService ) ,
147- onFileCreate : ( cb ) : void => {
148- getService < IFileService > ( IFileService ) . onAfterOperation ( ( e ) => {
149- if ( e . operation === FileOperation . CREATE ) {
150- cb ( e . resource . path ) ;
151- }
152- } ) ;
153- } ,
154- onFileMove : ( cb ) : void => {
155- getService < IFileService > ( IFileService ) . onAfterOperation ( ( e ) => {
156- if ( e . operation === FileOperation . MOVE ) {
157- cb ( e . resource . path , e . target ? e . target . resource . path : undefined ! ) ;
158- }
159- } ) ;
160- } ,
161- onFileDelete : ( cb ) : void => {
162- getService < IFileService > ( IFileService ) . onAfterOperation ( ( e ) => {
163- if ( e . operation === FileOperation . DELETE ) {
164- cb ( e . resource . path ) ;
165- }
166- } ) ;
167- } ,
168- onFileSaved : ( cb ) : void => {
169- getService < ITextFileService > ( ITextFileService ) . models . onModelSaved ( ( e ) => {
170- cb ( e . resource . path ) ;
171- } ) ;
172- } ,
173- onFileCopy : ( cb ) : void => {
174- getService < IFileService > ( IFileService ) . onAfterOperation ( ( e ) => {
175- if ( e . operation === FileOperation . COPY ) {
176- cb ( e . resource . path , e . target ? e . target . resource . path : undefined ! ) ;
177- }
178- } ) ;
179- } ,
180- onModelAdded : ( cb ) : void => {
181- getService < IModelService > ( IModelService ) . onModelAdded ( ( e ) => {
182- cb ( e . uri . path , e . getLanguageIdentifier ( ) . language ) ;
183- } ) ;
184- } ,
185- onModelRemoved : ( cb ) : void => {
186- getService < IModelService > ( IModelService ) . onModelRemoved ( ( e ) => {
187- cb ( e . uri . path , e . getLanguageIdentifier ( ) . language ) ;
188- } ) ;
189- } ,
190- onModelLanguageChange : ( cb ) : void => {
191- getService < IModelService > ( IModelService ) . onModelModeChanged ( ( e ) => {
192- cb ( e . model . uri . path , e . model . getLanguageIdentifier ( ) . language , e . oldModeId ) ;
193- } ) ;
194- } ,
195- onTerminalAdded : ( cb ) : void => {
196- getService < ITerminalService > ( ITerminalService ) . onInstanceCreated ( ( ) => cb ( ) ) ;
197- } ,
198- onTerminalRemoved : ( cb ) : void => {
199- getService < ITerminalService > ( ITerminalService ) . onInstanceDisposed ( ( ) => cb ( ) ) ;
200- } ,
115+ Registry . as < ViewletRegistry > ( ViewletExtensions . Viewlets ) . registerViewlet (
116+ new ViewletDescriptor ( CustomViewlet as any , id , containerName , cssClass , undefined , URI . parse ( icon ) ) ,
117+ ) ;
118+
119+ Registry . as < IWorkbenchActionRegistry > ( ActionExtensions . WorkbenchActions ) . registerWorkbenchAction (
120+ new SyncActionDescriptor ( OpenCustomViewletAction as any , id , localize ( "showViewlet" , "Show {0}" , containerName ) ) ,
121+ "View: Show {0}" ,
122+ localize ( "view" , "View" ) ,
123+ ) ;
124+
125+ // Generate CSS to show the icon in the activity bar.
126+ const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${ cssClass } ` ;
127+ createCSSRule ( iconClass , `-webkit-mask: url('${ icon } ') no-repeat 50% 50%` ) ;
128+
129+ const container = Registry . as < IViewContainersRegistry > ( ViewsExtensions . ViewContainersRegistry ) . registerViewContainer ( containerId ) ;
130+ Registry . as < IViewsRegistry > ( ViewsExtensions . ViewsRegistry ) . registerViews ( [ {
131+ id : viewId ,
132+ name : viewName ,
133+ ctorDescriptor : { ctor : CustomTreeViewPanel } ,
134+ treeView : getService ( IInstantiationService ) . createInstance ( CustomTreeView as any , viewId , container ) ,
135+ } ] as ITreeViewDescriptor [ ] , container ) ;
201136 } ,
202- // @ts -ignore
203- MenuId : MenuId ,
204- Severity : Severity ,
205- // @ts -ignore
206- StatusbarAlignment : StatusbarAlignment ,
207137 } ;
208138} ;
209139
@@ -282,3 +212,59 @@ class FileSystemProvider implements IFileSystemProvider {
282212 throw new Error ( "not implemented" ) ;
283213 }
284214}
215+
216+ class TreeViewDataProvider < T > implements ITreeViewDataProvider {
217+ private readonly root = Symbol ( "root" ) ;
218+ private readonly values = new Map < string , T > ( ) ;
219+ private readonly children = new Map < T | Symbol , ITreeItem [ ] > ( ) ;
220+
221+ public constructor ( private readonly provider : vscode . TreeDataProvider < T > ) { }
222+
223+ public async getChildren ( item ?: ITreeItem ) : Promise < ITreeItem [ ] > {
224+ const value = item && this . itemToValue ( item ) ;
225+ const children = await Promise . all (
226+ ( await this . provider . getChildren ( value ) || [ ] )
227+ . map ( async ( childValue ) => {
228+ const treeItem = await this . provider . getTreeItem ( childValue ) ;
229+ const handle = this . createHandle ( treeItem ) ;
230+ this . values . set ( handle , childValue ) ;
231+ return {
232+ handle,
233+ collapsibleState : TreeItemCollapsibleState . Collapsed ,
234+ } ;
235+ } )
236+ ) ;
237+
238+ this . clear ( value || this . root , item ) ;
239+ this . children . set ( value || this . root , children ) ;
240+
241+ return children ;
242+ }
243+
244+ public dispose ( ) : void {
245+ throw new Error ( "not implemented" ) ;
246+ }
247+
248+ private itemToValue ( item : ITreeItem ) : T {
249+ if ( ! this . values . has ( item . handle ) ) {
250+ throw new Error ( `No element found with handle ${ item . handle } ` ) ;
251+ }
252+ return this . values . get ( item . handle ) ! ;
253+ }
254+
255+ private clear ( value : T | Symbol , item ?: ITreeItem ) : void {
256+ if ( this . children . has ( value ) ) {
257+ this . children . get ( value ) ! . map ( ( c ) => this . clear ( this . itemToValue ( c ) , c ) ) ;
258+ this . children . delete ( value ) ;
259+ }
260+ if ( item ) {
261+ this . values . delete ( item . handle ) ;
262+ }
263+ }
264+
265+ private createHandle ( item : vscode . TreeItem ) : string {
266+ return item . id
267+ ? `coder-tree-item-id/${ item . id } `
268+ : `coder-tree-item-uuid/${ generateUuid ( ) } ` ;
269+ }
270+ }
0 commit comments