From fac0145820685e358a0abc4fa2937e5c90f465a2 Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Thu, 12 Mar 2026 01:40:24 +0100 Subject: [PATCH 1/2] Add DABs LSP language client for deployment-aware features Introduces a BundleLSPClient that spawns `databricks bundle lsp` via stdio to provide deployment-aware features for bundle YAML files: - Document links: Ctrl+click on resource keys to open in workspace - Hover: Shows resource ID, name, and workspace link The client connects to the CLI's new hidden LSP server and activates for all bundle YAML files (databricks.yml, databricks.yaml, etc.). Stacks with the existing Red Hat YAML extension. Depends on: databricks/cli#4714 Co-Authored-By: Claude Opus 4.6 --- packages/databricks-vscode/package.json | 1 + .../src/bundle/BundleLSPClient.ts | 93 +++++++++++++++++++ packages/databricks-vscode/src/extension.ts | 15 +++ yarn.lock | 45 +++++++++ 4 files changed, 154 insertions(+) create mode 100644 packages/databricks-vscode/src/bundle/BundleLSPClient.ts diff --git a/packages/databricks-vscode/package.json b/packages/databricks-vscode/package.json index 52b6166a3..b7918d7c0 100644 --- a/packages/databricks-vscode/package.json +++ b/packages/databricks-vscode/package.json @@ -1201,6 +1201,7 @@ "minimatch": "^10.0.1", "shell-quote": "^1.8.1", "triple-beam": "^1.4.1", + "vscode-languageclient": "^9.0.1", "winston": "^3.11.0", "yaml": "^2.3.4" }, diff --git a/packages/databricks-vscode/src/bundle/BundleLSPClient.ts b/packages/databricks-vscode/src/bundle/BundleLSPClient.ts new file mode 100644 index 000000000..eb3592f13 --- /dev/null +++ b/packages/databricks-vscode/src/bundle/BundleLSPClient.ts @@ -0,0 +1,93 @@ +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, +} from "vscode-languageclient/node"; +import {Disposable, Uri, workspace} from "vscode"; +import {CliWrapper} from "../cli/CliWrapper"; + +/** + * Manages the lifecycle of the DABs Language Server Protocol client. + * Spawns `databricks bundle lsp` and connects via stdio to provide + * deployment-aware features (document links, hover) for bundle YAML files. + */ +export class BundleLSPClient implements Disposable { + private client: LanguageClient | undefined; + private readonly cli: CliWrapper; + + constructor(cli: CliWrapper) { + this.cli = cli; + } + + async start(workspaceFolder: Uri, target?: string): Promise { + // Stop existing client if running. + await this.stop(); + + const args = ["bundle", "lsp"]; + if (target) { + args.push("--target", target); + } + + const serverOptions: ServerOptions = { + command: this.cli.cliPath, + args: args, + options: { + cwd: workspaceFolder.fsPath, + }, + }; + + const clientOptions: LanguageClientOptions = { + documentSelector: [ + { + scheme: "file", + language: "yaml", + pattern: "**/databricks.yml", + }, + { + scheme: "file", + language: "yaml", + pattern: "**/databricks.yaml", + }, + { + scheme: "file", + language: "yaml", + pattern: "**/bundle.yml", + }, + { + scheme: "file", + language: "yaml", + pattern: "**/bundle.yaml", + }, + ], + workspaceFolder: { + uri: workspaceFolder, + name: workspace.name ?? "workspace", + index: 0, + }, + }; + + this.client = new LanguageClient( + "databricks-bundle-lsp", + "Databricks Bundle LSP", + serverOptions, + clientOptions + ); + + await this.client.start(); + } + + async stop(): Promise { + if (this.client) { + try { + await this.client.stop(); + } catch { + // Client may already be stopped. + } + this.client = undefined; + } + } + + dispose(): void { + this.stop(); + } +} diff --git a/packages/databricks-vscode/src/extension.ts b/packages/databricks-vscode/src/extension.ts index 4713b02eb..5cc701869 100644 --- a/packages/databricks-vscode/src/extension.ts +++ b/packages/databricks-vscode/src/extension.ts @@ -50,6 +50,7 @@ import { BundleFileSet, registerBundleAutocompleteProvider, } from "./bundle"; +import {BundleLSPClient} from "./bundle/BundleLSPClient"; import {showWhatsNewPopup} from "./whatsNewPopup"; import {BundleValidateModel} from "./bundle/models/BundleValidateModel"; import {ConfigModel} from "./configuration/models/ConfigModel"; @@ -890,6 +891,20 @@ export async function activate( ); }); + // Start the DABs LSP client for deployment-aware features (document links, hover). + const bundleLSPClient = new BundleLSPClient(cli); + context.subscriptions.push(bundleLSPClient); + + const workspaceFolder = workspace.workspaceFolders?.[0]?.uri; + if (workspaceFolder) { + bundleLSPClient.start(workspaceFolder).catch((e) => { + logging.NamedLogger.getOrCreate(Loggers.Extension).error( + "Failed to start bundle LSP: ", + e + ); + }); + } + setDbnbCellLimits(workspaceFolderManager, connectionManager).catch((e) => { logging.NamedLogger.getOrCreate(Loggers.Extension).error( "Error while setting jupyter configs for parsing databricks notebooks", diff --git a/yarn.lock b/yarn.lock index bff6cb6c3..0189ec28c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3799,6 +3799,7 @@ __metadata: ts-node: ^10.9.2 typescript: ^5.3.3 vsce: ^2.15.0 + vscode-languageclient: ^9.0.1 wdio-video-reporter: ^5.1.4 wdio-vscode-service: ^6.0.2 winston: ^3.11.0 @@ -9520,6 +9521,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.3.7": + version: 7.7.4 + resolution: "semver@npm:7.7.4" + bin: + semver: bin/semver.js + checksum: 9b4a6a58e98b9723fafcafa393c9d4e8edefaa60b8dfbe39e30892a3604cf1f45f52df9cfb1ae1a22b44c8b3d57fec8a9bb7b3e1645431587cb272399ede152e + languageName: node + linkType: hard + "semver@npm:^7.5.2, semver@npm:^7.5.4": version: 7.5.4 resolution: "semver@npm:7.5.4" @@ -10840,6 +10850,41 @@ __metadata: languageName: node linkType: hard +"vscode-jsonrpc@npm:8.2.0": + version: 8.2.0 + resolution: "vscode-jsonrpc@npm:8.2.0" + checksum: f302a01e59272adc1ae6494581fa31c15499f9278df76366e3b97b2236c7c53ebfc71efbace9041cfd2caa7f91675b9e56f2407871a1b3c7f760a2e2ee61484a + languageName: node + linkType: hard + +"vscode-languageclient@npm:^9.0.1": + version: 9.0.1 + resolution: "vscode-languageclient@npm:9.0.1" + dependencies: + minimatch: ^5.1.0 + semver: ^7.3.7 + vscode-languageserver-protocol: 3.17.5 + checksum: ff30e5a9aac6726a88fe443fd631fe7e6130225299667c13162547f0a13ca2548d3f277d68cfb3ef6dc1810c048b2cf0e05024e1bcbd11982cd8acf681a67873 + languageName: node + linkType: hard + +"vscode-languageserver-protocol@npm:3.17.5": + version: 3.17.5 + resolution: "vscode-languageserver-protocol@npm:3.17.5" + dependencies: + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 + checksum: dfb42d276df5dfea728267885b99872ecff62f6c20448b8539fae71bb196b420f5351c5aca7c1047bf8fb1f89fa94a961dce2bc5bf7e726198f4be0bb86a1e71 + languageName: node + linkType: hard + +"vscode-languageserver-types@npm:3.17.5": + version: 3.17.5 + resolution: "vscode-languageserver-types@npm:3.17.5" + checksum: 79b420e7576398d396579ca3a461c9ed70e78db4403cd28bbdf4d3ed2b66a2b4114031172e51fad49f0baa60a2180132d7cb2ea35aa3157d7af3c325528210ac + languageName: node + linkType: hard + "vscode-uri@npm:^3.0.8": version: 3.0.8 resolution: "vscode-uri@npm:3.0.8" From eeeb710294d43e10366f020fa25cab8b5ad4c9c6 Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Thu, 12 Mar 2026 02:32:33 +0100 Subject: [PATCH 2/2] Update LSP command path to experimental bundle-lsp The CLI moved the LSP server from `databricks bundle lsp` to `databricks experimental bundle-lsp`. Co-Authored-By: Claude Opus 4.6 --- packages/databricks-vscode/src/bundle/BundleLSPClient.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/databricks-vscode/src/bundle/BundleLSPClient.ts b/packages/databricks-vscode/src/bundle/BundleLSPClient.ts index eb3592f13..82988b9bf 100644 --- a/packages/databricks-vscode/src/bundle/BundleLSPClient.ts +++ b/packages/databricks-vscode/src/bundle/BundleLSPClient.ts @@ -8,7 +8,7 @@ import {CliWrapper} from "../cli/CliWrapper"; /** * Manages the lifecycle of the DABs Language Server Protocol client. - * Spawns `databricks bundle lsp` and connects via stdio to provide + * Spawns `databricks experimental bundle-lsp` and connects via stdio to provide * deployment-aware features (document links, hover) for bundle YAML files. */ export class BundleLSPClient implements Disposable { @@ -23,7 +23,7 @@ export class BundleLSPClient implements Disposable { // Stop existing client if running. await this.stop(); - const args = ["bundle", "lsp"]; + const args = ["experimental", "bundle-lsp"]; if (target) { args.push("--target", target); } @@ -68,7 +68,7 @@ export class BundleLSPClient implements Disposable { this.client = new LanguageClient( "databricks-bundle-lsp", - "Databricks Bundle LSP", + "Databricks Experimental Bundle LSP", serverOptions, clientOptions );