From d305ea13186e102b5d52c9f6176e0e1de368a67b Mon Sep 17 00:00:00 2001 From: Andreas Wirth Date: Thu, 18 Jun 2026 11:24:44 +0200 Subject: [PATCH 1/2] Various quality of live improvements: - Filter releases by a minimum supported version when downloading from gh - Set "embedded lsp activated" toggle to true when re-configuring embedded lsp - Add further hints what to do in error cases --- src/extension.ts | 14 +++++++++++--- src/sammCliDownloader.ts | 2 ++ src/settings.ts | 7 ++++--- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 3290c0a..8bc4388 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -38,7 +38,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { const logOutputChannel = vscode.window.createOutputChannel('RDF/Turtle and SAMM Aspect Models Language Server', { log: true }); context.subscriptions.push(logOutputChannel); outputChannel = logOutputChannel; - settings = new TurtleExtensionSettings(context); + settings = new TurtleExtensionSettings(); sammCliDownloader = new SammCliDownloader(context, settings, outputChannel); languageClient = new TurtleLanguageClient(outputChannel, settings.getSammCliLspServerPort(), settings.getLanguageClientTraceLevel()); aspectValidationController = new AspectValidationController(createUnavailableClient(), vscode.window, vscode.workspace, outputChannel); @@ -81,8 +81,13 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { function queueLanguageServicesRestart(reason: string): Promise { restartChain = restartChain .then(() => restartLanguageServices(reason)) - .catch(error => { - vscode.window.showErrorMessage(`Failed to start required language services: ${error instanceof Error ? error.message : String(error)}`); + .catch(async error => { + const selection = await vscode.window.showErrorMessage(`Failed to start required language services: ${error instanceof Error ? error.message : String(error)}`, 'Configure SAMM CLI Executable', 'Check Extension Settings'); + if (selection === 'Configure SAMM CLI Executable') { + void selectSammCliExecutable(); + } else if (selection === 'Check Extension Settings') { + void vscode.commands.executeCommand('workbench.action.openSettings', 'turtle.languageServerSettings'); + } }); return restartChain; @@ -188,6 +193,7 @@ async function selectSammCliExecutable(): Promise { return; } await settings.setSammCliPath(selectedPath); + await settings.setEmbeddedLanguageServerStartEnabled(true); restartReason = `Changed SAMM CLI to custom executable: ${selectedPath}`; } else { if (!pick.releaseTag) { @@ -199,6 +205,7 @@ async function selectSammCliExecutable(): Promise { } const downloadedPath = await sammCliDownloader.downloadRelease(pick.releaseTag, downloadType); await settings.setSammCliPath(downloadedPath); + await settings.setEmbeddedLanguageServerStartEnabled(true); restartReason = `Changed SAMM CLI to GitHub release ${pick.releaseTag} (${downloadType === 'jar' ? 'JAR' : 'native executable'})`; } @@ -230,6 +237,7 @@ async function promptForDownloadType(): Promise<'native' | 'jar' | undefined> { async function promptForCustomExecutablePath(): Promise { const selection = await vscode.window.showOpenDialog({ + defaultUri: vscode.Uri.file(settings.getSammCliPath() || ''), canSelectFiles: true, canSelectFolders: false, canSelectMany: false, diff --git a/src/sammCliDownloader.ts b/src/sammCliDownloader.ts index 5de0d92..2e83336 100644 --- a/src/sammCliDownloader.ts +++ b/src/sammCliDownloader.ts @@ -37,6 +37,7 @@ interface GitHubRelease { const SAMM_CLI_STORAGE_DIR = 'SAMM CLI'; const RELEASES_PAGE_SIZE = 20; +const SAMM_CLI_MINIMUM_SUPPORTED_VERSION = 'v2.15.0'; export class SammCliDownloader { constructor( @@ -103,6 +104,7 @@ export class SammCliDownloader { const releases = await response.json() as Array; return releases .filter(release => !release.draft && !release.prerelease) + .filter(release => this.compareVersions(release.tag_name, SAMM_CLI_MINIMUM_SUPPORTED_VERSION) >= 0) .map(release => release.tag_name) .slice(0, limit); } diff --git a/src/settings.ts b/src/settings.ts index 58c8e9d..94da736 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -14,14 +14,15 @@ import * as vscode from 'vscode'; export class TurtleExtensionSettings { - constructor( - private readonly context: vscode.ExtensionContext, - ) { } isEmbeddedLanguageServerStartEnabled(): boolean { return vscode.workspace.getConfiguration('turtle.languageServerSettings').get('activateEmbeddedLanguageServer', true); } + async setEmbeddedLanguageServerStartEnabled(enabled: boolean): Promise { + await vscode.workspace.getConfiguration('turtle.languageServerSettings').update('activateEmbeddedLanguageServer', enabled, vscode.ConfigurationTarget.Global); + } + getSammCliPath(): string { return vscode.workspace.getConfiguration('turtle.languageServerSettings').get('sammCliPath', ''); } From cf448df0ca19dfba9878783d922651b47629cb67 Mon Sep 17 00:00:00 2001 From: Andreas Wirth Date: Thu, 18 Jun 2026 11:29:28 +0200 Subject: [PATCH 2/2] Remove custom 'onSave' hook, should be handled by lsp client --- src/aspectValidation.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/aspectValidation.ts b/src/aspectValidation.ts index 3e121e2..9dbf802 100644 --- a/src/aspectValidation.ts +++ b/src/aspectValidation.ts @@ -68,9 +68,6 @@ export class AspectValidationController { const editor = vscode.window.activeTextEditor; await this.validateDocument(editor?.document, 'manual'); }), - this.workspace.onDidSaveTextDocument(async document => { - await this.validateDocument(document, 'save'); - }), ); }