diff --git a/.github/workflows/test-smoke.yml b/.github/workflows/test-smoke.yml index 7c908e1822..8a7c37e2c8 100644 --- a/.github/workflows/test-smoke.yml +++ b/.github/workflows/test-smoke.yml @@ -43,8 +43,9 @@ jobs: - name: Install Go tools (Modules mode) run: | - go version - go run ./tools/installtools/main.go + cd .. + go version + go run ./vscode-gop/tools/installtools/main.go env: GO111MODULE: on EXT: "${{ matrix.os == 'windows-latest' && '.exe' || ''}}" diff --git a/src/commands/startLanguageServer.ts b/src/commands/startLanguageServer.ts index 7239167f4a..5c93287a05 100644 --- a/src/commands/startLanguageServer.ts +++ b/src/commands/startLanguageServer.ts @@ -11,6 +11,7 @@ import { GoExtensionContext } from '../context'; import { outputChannel, updateLanguageServerIconGoStatusBar } from '../goStatus'; import { getTool } from '../goTools'; import { + conf, buildLanguageClient, buildLanguageClientOption, buildLanguageServerConfig, @@ -75,7 +76,7 @@ export const startLanguageServer: CommandFactory = (ctx, goCtx) => { // If the language server is gopls, we enable a few additional features. if (cfg.serverName === 'gopls') { - const tool = getTool(cfg.serverName); + const tool = getTool(conf.lsName); if (tool) { // If the language server is turned on because it is enabled by default, // make sure that the user is using a new enough version. diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts index d49cc242e1..f13756dc4f 100644 --- a/src/goInstallTools.ts +++ b/src/goInstallTools.ts @@ -196,7 +196,7 @@ export async function installTools( const failed = await installToolWithGo(tool, goForInstall, envForTools); if (failed) { failures.push({ tool, reason: failed }); - } else if (tool.name === 'gopls') { + } else if (tool.name === 'goxls' || tool.name === 'gopls') { // Restart the language server if a new binary has been installed. vscode.commands.executeCommand('gop.languageserver.restart', RestartReason.INSTALLATION); } @@ -416,7 +416,11 @@ export async function promptForMissingTool(toolName: string) { // Offer the option to install all tools. installOptions.push('Install All'); } - const cmd = `go install -v ${getImportPathWithVersion(tool, undefined, goVersion)}`; + let goCmd = 'go'; + if (tool.name == 'goxls') { + goCmd = 'gop'; + } + const cmd = `${goCmd} install -v ${getImportPathWithVersion(tool, undefined, goVersion)}`; const selected = await vscode.window.showErrorMessage( `The "${tool.name}" command is not available. Run "${cmd}" to install.`, ...installOptions @@ -466,7 +470,7 @@ export async function promptForUpdatingTool( } let choices: string[] = ['Update']; - if (toolName === 'gopls') { + if (toolName === 'goxls' || toolName === 'gopls') { choices = ['Always Update', 'Update Once', 'Release Notes']; } if (toolName === 'dlv') { diff --git a/src/goToolsInformation.ts b/src/goToolsInformation.ts index 5d632e5b60..7d7bbd65b0 100644 --- a/src/goToolsInformation.ts +++ b/src/goToolsInformation.ts @@ -201,19 +201,33 @@ export const allToolsInformation: { [key: string]: Tool } = { description: 'Linter', defaultVersion: 'v1.3.2' }, + 'goxls': { + name: 'goxls', // goxls: Go+ + importPath: 'github.com/goplus/goxls', + modulePath: 'github.com/goplus/goxls', + replacedByGopls: false, // lol + isImportant: true, + description: 'Go+ Language Server', + usePrereleaseInPreviewMode: true, + minimumGoVersion: semver.coerce('1.18'), + latestVersion: semver.parse('v0.13.2'), + latestVersionTimestamp: moment('2023-11-10', 'YYYY-MM-DD'), + latestPrereleaseVersion: semver.parse('v0.13.2'), + latestPrereleaseVersionTimestamp: moment('2023-11-10', 'YYYY-MM-DD') + }, 'gopls': { name: 'gopls', - importPath: 'github.com/goplus/tools/goxls', // goxls: Go+ - modulePath: 'github.com/goplus/tools/goxls', + importPath: 'golang.org/x/tools/gopls', + modulePath: 'golang.org/x/tools/gopls', replacedByGopls: false, // lol isImportant: true, - description: 'Go+ Language Server', + description: 'Language Server from Google', usePrereleaseInPreviewMode: true, minimumGoVersion: semver.coerce('1.18'), - latestVersion: semver.parse('v0.1.0'), - latestVersionTimestamp: moment('2023-10-11', 'YYYY-MM-DD'), - latestPrereleaseVersion: semver.parse('v0.1.0'), - latestPrereleaseVersionTimestamp: moment('2023-10-11', 'YYYY-MM-DD') + latestVersion: semver.parse('v0.14.1'), + latestVersionTimestamp: moment('2023-10-26', 'YYYY-MM-DD'), + latestPrereleaseVersion: semver.parse('v0.14.1'), + latestPrereleaseVersionTimestamp: moment('2023-10-26', 'YYYY-MM-DD') }, 'dlv': { name: 'dlv', diff --git a/src/language/goLanguageServer.ts b/src/language/goLanguageServer.ts index 8da4d2e5ae..6fb1c42886 100644 --- a/src/language/goLanguageServer.ts +++ b/src/language/goLanguageServer.ts @@ -170,7 +170,7 @@ export function scheduleGoplsSuggestions(goCtx: GoExtensionContext) { }; */ const installGopls = async (cfg: LanguageServerConfig) => { - const tool = getTool('gopls'); + const tool = getTool(conf.lsName); const versionToUpdate = await shouldUpdateLanguageServer(tool, cfg); if (!versionToUpdate) { return; @@ -184,7 +184,7 @@ export function scheduleGoplsSuggestions(goCtx: GoExtensionContext) { const toolVersion = { ...tool, version: versionToUpdate }; // ToolWithVersion await installTools([toolVersion], goVersion, true); } else { - console.log(`gopls ${versionToUpdate} is too new, try to update later`); + console.log(`goxls ${versionToUpdate} is too new, try to update later`); } } else { promptForUpdatingTool(tool.name, versionToUpdate); @@ -1027,7 +1027,9 @@ export function getLanguageServerToolPath(): string | undefined { return; } // Get the path to gopls (getBinPath checks for alternate tools). - const goplsBinaryPath = getBinPath('gopls'); + // goxls: use goxls instead of gopls + // const goplsBinaryPath = getBinPath('gopls'); + const goplsBinaryPath = getBinPath(conf.lsName); if (path.isAbsolute(goplsBinaryPath)) { return goplsBinaryPath; } @@ -1072,8 +1074,11 @@ export async function shouldUpdateLanguageServer( if (!cfg) { return null; } - // Only support updating gopls for now. - if (tool.name !== 'gopls' || (!mustCheck && (cfg.checkForUpdates === 'off' || extensionInfo.isInCloudIDE))) { + // Only support updating gopls/goxls for now. + if ( + (tool.name !== 'gopls' && tool.name !== 'goxls') || + (!mustCheck && (cfg.checkForUpdates === 'off' || extensionInfo.isInCloudIDE)) + ) { return null; } if (!cfg.enabled) { @@ -1135,6 +1140,10 @@ export async function shouldUpdateLanguageServer( return semver.lt(usersVersionSemver!, latestVersion!) ? latestVersion : null; } +export const conf = { + lsName: 'goxls' +}; + /** * suggestUpdateGopls will make sure the user is using the latest version of `gopls`, * when go.useLanguageServer is changed to true by default. @@ -1163,7 +1172,7 @@ export async function suggestUpdateGopls(tool: Tool, cfg: LanguageServerConfig): } const updateMsg = - "'gopls' is now enabled by default and you are using an old version. Please [update 'gopls'](https://github.com/golang/tools/blob/master/gopls/README.md#installation) for the best experience."; + "'goxls' is now enabled by default and you are using an old version. Please [update 'goxls'](https://github.com/goplus/goxls/blob/main/README.md#installation) for the best experience."; promptForUpdatingTool(tool.name, latestVersion, false, updateMsg); } @@ -1362,7 +1371,7 @@ export async function suggestGoplsIssueReport( // The user may have an outdated version of gopls, in which case we should // just prompt them to update, not file an issue. - const tool = getTool('gopls'); + const tool = getTool(conf.lsName); if (tool) { const versionToUpdate = await shouldUpdateLanguageServer(tool, goCtx.latestConfig, true); if (versionToUpdate) { diff --git a/test/gopls/index.ts b/test/gopls/index.ts index 4e5cf073c9..c7fcf35307 100644 --- a/test/gopls/index.ts +++ b/test/gopls/index.ts @@ -7,6 +7,8 @@ import glob from 'glob'; import Mocha from 'mocha'; import * as path from 'path'; +import { conf } from '../../src/language/goLanguageServer'; + export function run(): Promise { // Create the mocha test const mocha = new Mocha({ @@ -20,6 +22,7 @@ export function run(): Promise { const testsRoot = path.resolve(__dirname, '..'); return new Promise((c, e) => { + conf.lsName = 'gopls'; glob('gopls/**.test.js', { cwd: testsRoot }, (err, files) => { if (err) { return e(err); diff --git a/tools/installtools/main.go b/tools/installtools/main.go index f72d468b2f..2c0f67b62d 100644 --- a/tools/installtools/main.go +++ b/tools/installtools/main.go @@ -16,6 +16,10 @@ import ( "strings" ) +const ( + gopVer = 0 // use `gop` instead of `go` +) + // finalVersion encodes the fact that the specified tool version // is the known last version that can be buildable with goMinorVersion. type finalVersion struct { @@ -36,6 +40,7 @@ var tools = []struct { }{ // TODO: auto-generate based on allTools.ts.in. {"golang.org/x/tools/gopls", "", true, nil}, + {"github.com/goplus/goxls", "", false, []finalVersion{{gopVer, "v0.13.2"}}}, {"github.com/acroca/go-symbols", "", false, nil}, {"github.com/cweill/gotests/gotests", "", false, nil}, {"github.com/davidrjenni/reftools/cmd/fillstruct", "", false, nil}, @@ -55,13 +60,16 @@ var tools = []struct { // pickVersion returns the version to install based on the supported // version list. -func pickVersion(goMinorVersion int, versions []finalVersion, defaultVersion string) string { +func pickVersion(goMinorVersion int, versions []finalVersion, defaultVersion string) (string, bool) { for _, v := range versions { + if v.goMinorVersion == gopVer { + return v.version, true // use gop + } if goMinorVersion <= v.goMinorVersion { - return v.version + return v.version, false } } - return defaultVersion + return defaultVersion, false } func main() { @@ -140,12 +148,15 @@ func installTools(binDir string, goMinorVersion int) error { } env := append(os.Environ(), "GO111MODULE=on") for _, tool := range tools { - ver := pickVersion(goMinorVersion, tool.versions, pickLatest(tool.path, tool.preferPreview)) + ver, useGop := pickVersion(goMinorVersion, tool.versions, pickLatest(tool.path, tool.preferPreview)) path := tool.path + "@" + ver cmd := exec.Command("go", installCmd, path) + if useGop { + cmd = exec.Command("gop", "install", path) + } cmd.Env = env cmd.Dir = dir - fmt.Println("go", installCmd, path) + fmt.Println(cmd) if out, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("installing %v: %s\n%v", path, out, err) } diff --git a/tools/installtools/main_test.go b/tools/installtools/main_test.go index d8b3d8de2d..98f75f0cea 100644 --- a/tools/installtools/main_test.go +++ b/tools/installtools/main_test.go @@ -37,7 +37,7 @@ func Test_pickVersion(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { for goMinorVersion, want := range tt.want { - if got := pickVersion(goMinorVersion, tt.versions, "latest"); got != want { + if got, _ := pickVersion(goMinorVersion, tt.versions, "latest"); got != want { t.Errorf("pickVersion(go 1.%v) = %v, want %v", goMinorVersion, got, want) } }