import { ExtensionContext , LanguageClient , LanguageClientOptions , commands , services , window , workspace } from 'coc.nvim' ; import { ChildProcess , spawn } from 'child_process' ; import os from 'os' ; import { commandExists , goBinPath , installGoBin } from './utils/tools' ; import { checkGopls , installGomodifytags , installGoplay , installGopls , installGotests , installImpl , installTools , version } from './commands' ; import { addTags , clearTags , removeTags } from './utils/modify-tags' ; import { getConfig , setStoragePath } from './utils/config' ; import { activeTextDocument } from './editor' ; import { GOPLS } from './binaries' ; import { generateTestsAll , generateTestsExported , generateTestsFunction , toogleTests } from './utils/tests' ; import { openPlayground } from './utils/playground' ; import { generateImplStubs } from './utils/impl' ; import { goplsTidy } from './utils/lspcommands' ; const restartConfigs = [ 'go.goplsArgs' , 'go.goplsOptions' , 'go.goplsPath' , 'go.goplsUseDaemon' , ] ; export async function activate ( context ) { setStoragePath ( context . storagePath ) ; if ( getConfig ( ) . enable === false ) { return ; } registerGeneral ( context ) ; registerGopls ( context ) ; registerTest ( context ) ; registerTags ( context ) ; registerPlaygroud ( context ) ; registerGoImpl ( context ) ; registerTools ( context ) ; registerLspCommands ( context ) ; } async function registerGeneral ( context ) { context . subscriptions . push ( commands . registerCommand ( "go.version" , ( ) => version ( ) ) ) ; } async function registerGopls ( context ) { const config = getConfig ( ) ; const command = await goplsPath ( config . goplsPath ) ; if ( ! command ) { return ; } const args = config . goplsArgs ? [ ... config . goplsArgs ] : [ ] ; if ( config . goplsUseDaemon !== false && ! args . find ( arg => arg . startsWith ( '-remote' ) ) ) { args . push ( '-remote=auto' ) ; } const tmpdir = await workspace . nvim . eval ( '$TMPDIR' ) as string ; const server = ( ) : Promise < ChildProcess > => { return new Promise ( resolve => { resolve ( spawn ( command , args , { cwd : workspace . cwd , env : { ... process . env , TMPDIR : tmpdir , ... config . goplsEnv } , } ) ) ; } ) ; } ; const clientOptions = { documentSelector : [ 'go' , 'gomod' ] , initializationOptions : ( ) => getConfig ( ) . goplsOptions , disableWorkspaceFolders : config . disable . workspaceFolders , disableDiagnostics : config . disable . diagnostics , disableCompletion : config . disable . completion , } ; const client = new LanguageClient ( 'go' , 'gopls' , server , clientOptions ) ; if ( config . checkForUpdates !== 'disabled' && ! config . goplsPath ) { await checkGopls ( client , config . checkForUpdates ) ; } context . subscriptions . push ( services . registLanguageClient ( client ) , workspace . onDidChangeConfiguration ( async ( e ) => { if ( restartConfigs . find ( k => e . affectsConfiguration ( k ) ) ) { await client . stop ( ) ; client . restart ( ) ; } } ) , commands . registerCommand ( "go.install.gopls" , ( ) => installGopls ( client ) ) ) ; } async function goplsPath ( goplsPath ) { if ( goplsPath ) { if ( goplsPath . startsWith ( '~' ) ) { goplsPath = os . homedir ( ) + goplsPath . slice ( 1 ) ; } if ( ! await commandExists ( goplsPath ) ) { window . showMessage ( `goplsPath is configured ("${ goplsPath }"), but does not exist!` , 'error' ) ; return null ; } return goplsPath ; } if ( ! await installGoBin ( GOPLS ) ) { return ; } return goBinPath ( GOPLS ) ; } async function registerGoImpl ( context ) { context . subscriptions . push ( commands . registerCommand ( "go.install.impl" , ( ) => installImpl ( ) ) , commands . registerCommand ( "go.impl.cursor" , async ( ) => generateImplStubs ( await activeTextDocument ( ) ) ) ) ; } async function registerTest ( context ) { context . subscriptions . push ( commands . registerCommand ( "go.install.gotests" , ( ) => installGotests ( ) ) , commands . registerCommand ( "go.test.generate.file" , async ( ) => generateTestsAll ( await activeTextDocument ( ) ) ) , commands . registerCommand ( "go.test.generate.exported" , async ( ) => generateTestsExported ( await activeTextDocument ( ) ) ) , commands . registerCommand ( "go.test.generate.function" , async ( ) => generateTestsFunction ( await activeTextDocument ( ) ) ) , commands . registerCommand ( "go.test.toggle" , async ( ) => toogleTests ( await activeTextDocument ( ) ) ) ) ; } async function registerTags ( context ) { context . subscriptions . push ( commands . registerCommand ( "go.install.gomodifytags" , ( ) => installGomodifytags ( ) ) , commands . registerCommand ( "go.tags.add" , async ( ... tags ) => addTags ( await activeTextDocument ( ) , { tags } ) ) , commands . registerCommand ( "go.tags.add.line" , async ( ... tags ) => addTags ( await activeTextDocument ( ) , { tags , selection : "line" } ) ) , commands . registerCommand ( "go.tags.add.prompt" , async ( ) => addTags ( await activeTextDocument ( ) , { prompt : true } ) ) , commands . registerCommand ( "go.tags.remove" , async ( ... tags ) => removeTags ( await activeTextDocument ( ) , { tags } ) ) , commands . registerCommand ( "go.tags.remove.line" , async ( ... tags ) => removeTags ( await activeTextDocument ( ) , { tags , selection : "line" } ) ) , commands . registerCommand ( "go.tags.remove.prompt" , async ( ) => removeTags ( await activeTextDocument ( ) , { prompt : true } ) ) , commands . registerCommand ( "go.tags.clear" , async ( ) => clearTags ( await activeTextDocument ( ) ) ) , commands . registerCommand ( "go.tags.clear.line" , async ( ) => clearTags ( await activeTextDocument ( ) , { selection : "line" } ) ) ) ; } async function registerPlaygroud ( context ) { context . subscriptions . push ( commands . registerCommand ( "go.install.goplay" , ( ) => installGoplay ( ) ) , commands . registerCommand ( "go.playground" , async ( ) => openPlayground ( await activeTextDocument ( ) ) ) ) ; } async function registerTools ( context ) { context . subscriptions . push ( commands . registerCommand ( "go.install.tools" , ( ) => installTools ( ) ) ) ; } async function registerLspCommands ( context ) { context . subscriptions . push ( commands . registerCommand ( "go.gopls.tidy" , goplsTidy ) ) ; }