import { BaseLanguageClient , commands , DynamicFeature , Event , RegistrationData , } from "coc.nvim" ; import { MetalsTreeRevealResult , MetalsTreeViewChildren , MetalsTreeViewDidChange , MetalsTreeViewNode , MetalsTreeViewNodeCollapseDidChange , MetalsTreeViewReveal , MetalsTreeViewVisibilityDidChange , ServerCommands , } from "metals-languageclient" ; import { Disposable , Emitter , ExecuteCommandParams , ExecuteCommandRequest , Position , RequestType , RPCMessageType , TextDocumentPositionParams , } from "vscode-languageserver-protocol" ; import { TextDocument } from "vscode-languageserver-textdocument" ; import { TreeViewProvider } from "./provider" ; export class TreeViewFeature implements DynamicFeature < void > { private requestType = new RequestType < void , any , void , void > ( "metals/treeView" ) ; private providerEmitter : Emitter < TreeViewProvider > = new Emitter ( ) ; private viewUpdaters : Map < string , Emitter < MetalsTreeViewNode > > = new Map ( ) ; private mbGotoCommandDisposable : Disposable | undefined = undefined ; constructor ( private _client ) { } public get messages ( ) : RPCMessageType { return this . requestType ; } public fillClientCapabilities ( ) { } public initialize ( ) { const client = this . _client ; client . onNotification ( MetalsTreeViewDidChange . type , ( params ) => { params . nodes . forEach ( ( node ) => { const viewId = node . viewId ; const mbViewUpdater = this . viewUpdaters . get ( viewId ) ; if ( mbViewUpdater === undefined ) { const updatesEmitter = new Emitter < MetalsTreeViewNode > ( ) ; const provider = { viewId , updatedNodes : updatesEmitter . event , loadNodeChildren : ( parentNode ? ) : Promise < MetalsTreeViewNode [ ] > => { const result = client . sendRequest ( MetalsTreeViewChildren . type , { viewId , nodeUri : parentNode , } ) . then ( ( response ) => response . nodes ) ; return Promise . resolve ( result ) ; } , loadParentInfo : ( document , position ) : Promise < MetalsTreeRevealResult > => { const tweakedPosition = { line : position . line + 1 , character : position . character , } ; const arg = { textDocument : { uri : document . uri , } , position : tweakedPosition , } ; return Promise . resolve ( client . sendRequest ( MetalsTreeViewReveal . type , arg ) ) ; } , sendTreeViewVisibilityNotification : ( visible ) : void => { client . sendNotification ( MetalsTreeViewVisibilityDidChange . type , { viewId , visible , } ) ; } , sendTreeNodeVisibilityNotification : ( childNode , collapsed ) : void => { client . sendNotification ( MetalsTreeViewNodeCollapseDidChange . type , { viewId , nodeUri : childNode , collapsed , } ) ; } , } ; this . providerEmitter . fire ( provider ) ; this . viewUpdaters . set ( viewId , updatesEmitter ) ; } else { mbViewUpdater . fire ( node ) ; } } ) ; } ) ; this . mbGotoCommandDisposable = commands . registerCommand ( `metals.${ ServerCommands . Goto }` , async ( ... args ) => { let params = { command : ServerCommands . Goto , arguments : args , } ; return client . sendRequest ( ExecuteCommandRequest . type , params ) . then ( undefined , ( error ) => { client . logFailedRequest ( ExecuteCommandRequest . type , error ) ; } ) ; } , null , true ) ; } public providerEvents ( ) { return this . providerEmitter . event ; } public register ( _message , _data ) { } public unregister ( _ ) { } public dispose ( ) { this . providerEmitter . dispose ( ) ; this . viewUpdaters . forEach ( ( emitter ) => emitter . dispose ( ) ) ; if ( this . mbGotoCommandDisposable !== undefined ) this . mbGotoCommandDisposable . dispose ( ) ; } }