import { CompletionItem , CompletionList , Position , TextDocument , CancellationToken , CompletionContext , LanguageClient , LanguageClientOptions , Middleware , ProvideCompletionItemsSignature , ProviderResult , ServerOptions , window , workspace } from 'coc.nvim' ; import net from 'net' ; import * as solargraph from 'solargraph-utils' ; export function makeLanguageClient ( configuration ) { let prepareStatus = window . createStatusBarItem ( 10 , { progress : true } ) ; prepareStatus . show ( ) ; let middleware = { provideCompletionItem : ( document , position , context , token , next ) : ProviderResult < CompletionItem [ ] | CompletionList > => { return Promise . resolve ( next ( document , position , context , token ) ) . then ( ( res ) => { let doc = workspace . getDocument ( document . uri ) ; if ( ! doc || ! res ) return [ ] ; let items = res . hasOwnProperty ( 'isIncomplete' ) ? ( res as CompletionList ) . items : res as CompletionItem [ ] ; let result = { isIncomplete : false , items } ; if ( items . length && items . every ( o => o . label . startsWith ( ':' ) ) ) { result . startcol = doc . fixStartcol ( position , [ ':' ] ) ; } return result ; } ) ; } } ; let clientOptions = { documentSelector : [ { scheme : 'file' , language : 'ruby' } , { scheme : 'file' , pattern : '**/Gemfile' } ] , synchronize : { configurationSection : 'solargraph' , fileEvents : workspace . createFileSystemWatcher ( '{**/*.rb,**/*.gemspec,**/Gemfile}' ) } , middleware , initializationOptions : { enablePages : true , viewsPath : configuration . viewsPath } } ; let selectClient = ( ) : ServerOptions => { let transport = workspace . getConfiguration ( 'solargraph' ) . transport ; if ( transport == 'stdio' ) { return ( ) => { return new Promise ( resolve => { let child = solargraph . commands . solargraphCommand ( [ 'stdio' ] , configuration ) ; child . on ( 'error' , err => { console . error ( 'Solargraph error:' , err . message ) ; } ) ; child . stderr . on ( 'data' , ( data ) => { console . log ( data . toString ( ) ) ; } ) ; child . on ( 'exit' , ( code , signal ) => { console . error ( 'Solargraph exited with code' , code , signal ) ; } ) ; resolve ( child ) ; } ) ; } ; } else if ( transport == 'socket' ) { return ( ) => { return new Promise ( ( resolve , reject ) => { let socketProvider = new solargraph . SocketProvider ( configuration ) ; socketProvider . start ( ) . then ( ( ) => { let socket = net . createConnection ( socketProvider . port , '127.0.0.1' ) ; resolve ( { reader : socket , writer : socket } ) ; } ) . catch ( err => { reject ( err ) ; } ) ; } ) ; } ; } else { return ( ) => { return new Promise ( resolve => { let socket = net . createConnection ( { host : workspace . getConfiguration ( 'solargraph' ) . externalServer . host , port : workspace . getConfiguration ( 'solargraph' ) . externalServer . port } ) ; resolve ( { reader : socket , writer : socket } ) ; } ) ; } ; } } ; let serverOptions = selectClient ( ) ; let client = new LanguageClient ( 'solargraph' , 'Ruby Language Server' , serverOptions , clientOptions ) ; let interval = setInterval ( ( ) => { prepareStatus . text = `Starting the Solargraph language server` ; } , 100 ) ; client . onReady ( ) . then ( ( ) => { clearInterval ( interval ) ; prepareStatus . dispose ( ) ; window . showMessage ( 'Solargraph is ready.' , 'more' ) ; } ) . catch ( ( ) => { clearInterval ( interval ) ; prepareStatus . dispose ( ) ; window . showMessage ( 'Solargraph failed to initialize.' , 'error' ) ; } ) ; return client ; }