Skip to content
Snippets Groups Projects
Commit a1660910 authored by Konstantin Ivanov's avatar Konstantin Ivanov
Browse files

Merge branch 'martoon/#1922-restart-on-ligo-path-update' into 'dev'

[#1922] Suggest restarting when LIGO path is changed

See merge request !3041
parents 2b6b18be 179d9ce5
No related branches found
No related tags found
Loading
Pipeline #1159513418 passed
author: Martoon
description: "\\nWhen changing LIGO path in settings, a suggestion will pop up to restart VSCode.\\n\\n"
merge_request: '3041'
title: "[#1922] Suggest restarting when LIGO path is changed"
type: fixed
\ No newline at end of file
import * as vscode from 'vscode';
import { Disposable } from "vscode-languageclient";
export type BinaryInfo = {
name: string,
path: string,
}
export const ligoBinaryInfo = {
name: 'ligo',
path: 'ligoLanguageServer.ligoBinaryPath'
}
/** Start detecting when path to LIGO is changed in config, and initiate client
* restart sequence. */
export function trackLigoPathChanges(): Disposable {
// We do the thing via subscribing on "configuration changed" event.
//
// However, this way, as the user enters the new path, we will get notified
// about all the intermediate values. To invoke restart exactly once, when
// config is changed we will show a prompt asking for manual restart once the
// user is ready.
// Helps to show the prompt only once per multiple small changes.
var changeInProgress = false;
return vscode.workspace.onDidChangeConfiguration(e => {
if (!e.affectsConfiguration(ligoBinaryInfo.path)) {
return
}
if (changeInProgress) {
return
}
changeInProgress = true
vscode.window.showInformationMessage(
"Restart is needed for LIGO path change to take effect.",
"Restart",
"Cancel"
).then(
selectedValue => {
changeInProgress = false
switch (selectedValue) {
case "Restart":
vscode.commands.executeCommand('workbench.action.reloadWindow');
return;
case "Cancel":
case undefined:
}
}
)
})
}
......@@ -6,6 +6,7 @@ import { LigoProtocolClient, showErrorWithOpenLaunchJson } from '../common/LigoP
import { ValidateValueCategory } from './messages'
import { createConfigSnippet, createRememberingQuickPick, getConfigPath, getModuleName, getParameterOrStorage } from './ui'
import { InputValueLang, isDefined, Maybe } from '../common/base'
import { ligoBinaryInfo } from '../common/config'
function createLogDir(logDir: string): void | undefined {
if (!fs.existsSync(logDir)) {
......@@ -42,7 +43,7 @@ export default class LigoDebugConfigurationProvider implements vscode.DebugConfi
private async tryToResolveConfigFromLigo(config: vscode.DebugConfiguration): Promise<vscode.DebugConfiguration> {
const pluginConfig = vscode.workspace.getConfiguration();
const binaryPath = getBinaryPath({ name: 'ligo', path: 'ligoLanguageServer.ligoBinaryPath' }, pluginConfig);
const binaryPath = getBinaryPath(ligoBinaryInfo, pluginConfig);
const maxSteps = pluginConfig.get<Maybe<number>>('ligoDebugger.maxSteps');
await this.client.sendMsg('setLigoConfig', { binaryPath, maxSteps });
......
......@@ -14,6 +14,7 @@ import { LigoProtocolClient } from './common/LigoProtocolClient';
import { DebuggerExtension } from './debugger/DebuggerExtension';
import LigoServer from './debugger/LigoServer';
import { getCurrentWorkspacePath } from './debugger/base';
import { trackLigoPathChanges } from './common/config';
const lspExtension = new LspExtension();
const debuggerExtension = new DebuggerExtension();
......@@ -25,6 +26,10 @@ export async function activate(context: vscode.ExtensionContext) {
const server = new LigoServer(getCurrentWorkspacePath()?.fsPath, adapterPath, []);
const client = new LigoProtocolClient(server.address());
context.subscriptions.push(
trackLigoPathChanges()
)
lspExtension.activate(ligoContext, server, client);
debuggerExtension.activate(ligoContext, server, client);
}
......
......@@ -18,11 +18,12 @@ import { BinaryNotFoundException } from './exceptions'
import { LigoExtension } from "../LigoExtension";
import { extensions } from './common'
import { changeLastContractPath, getBinaryPath, ligoBinaryInfo } from './commands/common';
import { changeLastContractPath, getBinaryPath } from './commands/common';
import { LigoContext } from '../common/LigoContext';
import { LigoProtocolClient } from '../common/LigoProtocolClient';
import LigoServer from '../debugger/LigoServer';
import { ligoBinaryInfo } from '../common/config';
export class LspExtension extends LigoExtension {
private languageServerClient: LanguageClient;
......@@ -82,10 +83,9 @@ export class LspExtension extends LigoExtension {
public activate(context: LigoContext, _server: LigoServer, protocolClient: LigoProtocolClient): void {
const config = vscode.workspace.getConfiguration()
let ligoPath: string
try {
ligoPath = getBinaryPath(ligoBinaryInfo, config)
ligoPath = getBinaryPath(ligoBinaryInfo)
} catch (err) {
if (err instanceof BinaryNotFoundException) {
ligoPath = undefined
......
......@@ -8,6 +8,7 @@ import { extensions } from '../common'
import * as ex from '../exceptions'
import { Maybe } from '../../common/base';
import { BinaryInfo } from '../../common/config';
export const ligoOutput = vscode.window.createOutputChannel('LIGO Compiler')
......@@ -15,16 +16,6 @@ export const ligoOutput = vscode.window.createOutputChannel('LIGO Compiler')
let lastContractPath: string;
type BinaryInfo = {
name: string,
path: string,
}
export const ligoBinaryInfo = {
name: 'ligo',
path: 'ligoLanguageServer.ligoBinaryPath'
}
export function changeLastContractPath(newPath: string) {
lastContractPath = newPath
}
......@@ -43,7 +34,8 @@ export function findBinaryPath(binaryName: string): string {
return execFileSync(find, [binaryName]).toString().trim().split('\n')[0]
}
export function getBinaryPath(info: BinaryInfo, config: vscode.WorkspaceConfiguration) {
export function getBinaryPath(info: BinaryInfo) {
const config = vscode.workspace.getConfiguration()
let binaryPath = config.get<string>(info.path)
if (binaryPath) {
return binaryPath
......@@ -118,7 +110,7 @@ export function executeCommand(
showOutput = true,
): string {
const contractInfo = getLastContractPath()
const ligoPath = getBinaryPath(binary, vscode.workspace.getConfiguration());
const ligoPath = getBinaryPath(binary);
const ligoJsonPath = findPackage(dirname(contractInfo.path))
if (commandArgs & CommandRequiredArguments.Path) {
......
import * as vscode from 'vscode';
import { createRememberingInputBox, createQuickPickBox } from '../ui'
import {
CommandRequiredArguments, executeCommand, getBinaryPath, getLastContractPath, ligoBinaryInfo
CommandRequiredArguments, executeCommand, getBinaryPath, getLastContractPath,
} from './common';
import * as ex from '../exceptions'
import { InputBoxType, InputValueLang, isDefined, Maybe } from '../../common/base';
......@@ -12,6 +10,7 @@ import { LigoProtocolClient } from '../../common/LigoProtocolClient';
import { getModuleName, getParameterOrStorage } from '../../debugger/ui';
import { ContractMetadata } from '../../debugger/base';
import { ValidateValueCategory } from '../../debugger/messages';
import { ligoBinaryInfo } from '../../common/config';
/* eslint-disable no-bitwise */
......@@ -43,7 +42,7 @@ const withProjectRootFlag = (args: string[]) => (projectRootDirectory: Maybe<str
}
async function prepareState(client: LigoProtocolClient): Promise<[string, string][]> {
const binaryPath = getBinaryPath(ligoBinaryInfo, vscode.workspace.getConfiguration())
const binaryPath = getBinaryPath(ligoBinaryInfo)
await client.sendMsg('initializeLanguageServerState', { binaryPath });
return (await client.sendMsg('setProgramPath', { program: getLastContractPath().path })).body.moduleNames.reverse();
}
......
......@@ -10,12 +10,13 @@ import {
LanguageClient,
} from 'vscode-languageclient/node'
import { extensionName } from './common'
import { getBinaryPath, ligoBinaryInfo } from './commands/common'
import { getBinaryPath } from './commands/common'
import { BinaryNotFoundException } from './exceptions'
import detectInstaller from 'detect-installer'
import { Readable } from 'stream'
import { Maybe } from '../common/base'
import { ligoBinaryInfo } from '../common/config'
type TagName = 'Static Linux binary' | 'Ligo Windows installer'
......@@ -51,9 +52,9 @@ async function withClientRestart<T>(client: LanguageClient, action: () => T): Pr
return result
}
async function updateLigoPath(config: vscode.WorkspaceConfiguration, path: string): Promise<void> {
return await config.update(
'ligoLanguageServer.ligoBinaryPath',
async function updateLigoPath(path: string): Promise<void> {
await vscode.workspace.getConfiguration().update(
ligoBinaryInfo.path,
path,
vscode.ConfigurationTarget.Global,
true,
......@@ -61,7 +62,6 @@ async function updateLigoPath(config: vscode.WorkspaceConfiguration, path: strin
}
export async function copyLigoBinary(
config: vscode.WorkspaceConfiguration,
client: LanguageClient,
ligoPath: string,
payload: Buffer,
......@@ -74,7 +74,7 @@ export async function copyLigoBinary(
fs.writeFileSync(ligoPath, payload, fileOptions)
fs.chmodSync(ligoPath, 0o755)
await updateLigoPath(config, ligoPath)
await updateLigoPath(ligoPath)
vscode.window.showInformationMessage(
`LIGO installed at: ${path.resolve(ligoPath)}. Please restart VS Code to use LIGO LSP.`,
)
......@@ -307,7 +307,6 @@ async function runPacmanUpgrade(client: LanguageClient): Promise<null> {
async function runStaticLinuxBinaryInstaller(
client: LanguageClient,
config: vscode.WorkspaceConfiguration,
ligoPath: Maybe<string>,
latestRelease: Release
): Promise<TagName | null> {
......@@ -332,7 +331,7 @@ async function runStaticLinuxBinaryInstaller(
ligoPath = path.join(uris[0].fsPath, 'ligo')
}
if (await copyLigoBinary(config, client, ligoPath, payload)) {
if (await copyLigoBinary(client, ligoPath, payload)) {
return latestRelease.tag_name
}
return null
......@@ -340,11 +339,10 @@ async function runStaticLinuxBinaryInstaller(
async function runStaticLinuxBinaryUpgrade(
client: LanguageClient,
config: vscode.WorkspaceConfiguration,
ligoPath: string,
latestRelease: Release
): Promise<TagName | null> {
return runStaticLinuxBinaryInstaller(client, config, ligoPath, latestRelease)
return runStaticLinuxBinaryInstaller(client, ligoPath, latestRelease)
}
type LinuxInstallMethod = "npm" | "pacman" | "yarn" | null
......@@ -419,14 +417,13 @@ async function askUserToUpgrade(platform: NodeJS.Platform, installer: InstallMet
async function runInstaller(
client: LanguageClient,
config: vscode.WorkspaceConfiguration,
platform: NodeJS.Platform,
answer: ChosenInstallMethod,
): Promise<boolean> {
switch (answer) {
case 'Static Binary': {
const latestRelease = await getLatestLigoRelease()
return !!await runStaticLinuxBinaryInstaller(client, config, undefined, latestRelease)
return !!await runStaticLinuxBinaryInstaller(client, undefined, latestRelease)
}
case 'GUI installer': {
const latestRelease = await getLatestLigoRelease()
......@@ -450,8 +447,8 @@ async function runInstaller(
return false
}
await updateLigoPath(config, uris[0].fsPath)
await updateLigoImpl(client, config)
await updateLigoPath(uris[0].fsPath)
await updateLigo(client)
return true
}
case 'Open Downloads':
......@@ -465,7 +462,6 @@ async function runInstaller(
async function runUpgrade(
client: LanguageClient,
config: vscode.WorkspaceConfiguration,
ligoPath: string,
latestRelease: Release,
platform: NodeJS.Platform,
......@@ -473,7 +469,7 @@ async function runUpgrade(
answer: ChosenUpgradeMethod,
): Promise<string | null> {
switch (answer) {
case 'Static Binary': return await runStaticLinuxBinaryUpgrade(client, config, ligoPath, latestRelease)
case 'Static Binary': return await runStaticLinuxBinaryUpgrade(client, ligoPath, latestRelease)
case 'Upgrade':
switch (installer) {
case 'brew': return await runBrewUpgrade(client)
......@@ -494,7 +490,6 @@ async function runUpgrade(
async function promptLigoUpdate(
client: LanguageClient,
config: vscode.WorkspaceConfiguration,
ligoPath: string,
installedVersionIdentifier: string | number,
): Promise<string | number> {
......@@ -523,24 +518,16 @@ async function promptLigoUpdate(
const installer: InstallMethod = await detectInstaller({ cwd: process.cwd() }).catch(_ => null)
const platform: NodeJS.Platform = os.platform()
const answer = await askUserToUpgrade(platform, installer, 'A new LIGO version is available.')
const tagName = await runUpgrade(client, config, ligoPath, latestRelease, platform, installer, answer)
const tagName = await runUpgrade(client, ligoPath, latestRelease, platform, installer, answer)
return tagName || installedVersionIdentifier
}
export default async function updateLigo(client: LanguageClient): Promise<void> {
const config = vscode.workspace.getConfiguration()
/* eslint-disable no-use-before-define */
return updateLigoImpl(client, config)
/* eslint-enable no-use-before-define */
}
async function showUpdateError(
client: LanguageClient,
errorMessage: string,
suggestUpdate: boolean,
ligoPath: string,
config: vscode.WorkspaceConfiguration
): Promise<boolean> {
const platform = os.platform()
const installer = await detectInstaller({ cwd: process.cwd() }).catch(_ => null)
......@@ -548,17 +535,17 @@ async function showUpdateError(
if (suggestUpdate) {
const latestRelease = getLatestLigoRelease()
const answer: ChosenUpgradeMethod = await askUserToUpgrade(platform, installer, errorMessage)
return !!await runUpgrade(client, config, ligoPath, await latestRelease, platform, installer, answer)
return !!await runUpgrade(client, ligoPath, await latestRelease, platform, installer, answer)
} else {
const answer: ChosenInstallMethod = await askUserToInstall(platform, errorMessage)
return await runInstaller(client, config, platform, answer)
return await runInstaller(client, platform, answer)
}
}
async function updateLigoImpl(client: LanguageClient, config: vscode.WorkspaceConfiguration): Promise<void> {
export default async function updateLigo(client: LanguageClient): Promise<void> {
let ligoPath: string
try {
ligoPath = getBinaryPath(ligoBinaryInfo, config)
ligoPath = getBinaryPath(ligoBinaryInfo)
} catch (err) {
if (err instanceof BinaryNotFoundException) {
ligoPath = undefined
......@@ -587,7 +574,6 @@ async function updateLigoImpl(client: LanguageClient, config: vscode.WorkspaceCo
`Could not find a LIGO installation on your computer or the installation is invalid. Pick one of the available installation methods. Details: ${err.message}. ${hint}`,
false,
ligoPath,
config,
)
if (!shouldContinue) {
......@@ -609,7 +595,6 @@ async function updateLigoImpl(client: LanguageClient, config: vscode.WorkspaceCo
'You need LIGO version 0.61.0 or newer so that `ligo lsp` may work. Closing the language server. Please update and try again.',
true,
ligoPath,
config,
)
throw new Error("Unsupported version")
}
......@@ -617,7 +602,7 @@ async function updateLigoImpl(client: LanguageClient, config: vscode.WorkspaceCo
async function validateSemver(version: string) {
const semverTest = semver.valid(semver.coerce(version))
if (semverTest) {
const newVersion = await promptLigoUpdate(client, config, ligoPath, semverTest)
const newVersion = await promptLigoUpdate(client, ligoPath, semverTest)
switch (typeof newVersion) {
case 'string':
if (semver.lt(newVersion, '1.0.0')) {
......@@ -647,7 +632,7 @@ async function updateLigoImpl(client: LanguageClient, config: vscode.WorkspaceCo
return
}
const newVersion = promptLigoUpdate(client, config, ligoPath, date)
const newVersion = promptLigoUpdate(client, ligoPath, date)
switch (typeof newVersion) {
case 'string':
validateSemver(version)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment