Skip to content

Commit fac0145

Browse files
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 <noreply@anthropic.com>
1 parent a8e0f7d commit fac0145

File tree

4 files changed

+154
-0
lines changed

4 files changed

+154
-0
lines changed

packages/databricks-vscode/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,7 @@
12011201
"minimatch": "^10.0.1",
12021202
"shell-quote": "^1.8.1",
12031203
"triple-beam": "^1.4.1",
1204+
"vscode-languageclient": "^9.0.1",
12041205
"winston": "^3.11.0",
12051206
"yaml": "^2.3.4"
12061207
},
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import {
2+
LanguageClient,
3+
LanguageClientOptions,
4+
ServerOptions,
5+
} from "vscode-languageclient/node";
6+
import {Disposable, Uri, workspace} from "vscode";
7+
import {CliWrapper} from "../cli/CliWrapper";
8+
9+
/**
10+
* Manages the lifecycle of the DABs Language Server Protocol client.
11+
* Spawns `databricks bundle lsp` and connects via stdio to provide
12+
* deployment-aware features (document links, hover) for bundle YAML files.
13+
*/
14+
export class BundleLSPClient implements Disposable {
15+
private client: LanguageClient | undefined;
16+
private readonly cli: CliWrapper;
17+
18+
constructor(cli: CliWrapper) {
19+
this.cli = cli;
20+
}
21+
22+
async start(workspaceFolder: Uri, target?: string): Promise<void> {
23+
// Stop existing client if running.
24+
await this.stop();
25+
26+
const args = ["bundle", "lsp"];
27+
if (target) {
28+
args.push("--target", target);
29+
}
30+
31+
const serverOptions: ServerOptions = {
32+
command: this.cli.cliPath,
33+
args: args,
34+
options: {
35+
cwd: workspaceFolder.fsPath,
36+
},
37+
};
38+
39+
const clientOptions: LanguageClientOptions = {
40+
documentSelector: [
41+
{
42+
scheme: "file",
43+
language: "yaml",
44+
pattern: "**/databricks.yml",
45+
},
46+
{
47+
scheme: "file",
48+
language: "yaml",
49+
pattern: "**/databricks.yaml",
50+
},
51+
{
52+
scheme: "file",
53+
language: "yaml",
54+
pattern: "**/bundle.yml",
55+
},
56+
{
57+
scheme: "file",
58+
language: "yaml",
59+
pattern: "**/bundle.yaml",
60+
},
61+
],
62+
workspaceFolder: {
63+
uri: workspaceFolder,
64+
name: workspace.name ?? "workspace",
65+
index: 0,
66+
},
67+
};
68+
69+
this.client = new LanguageClient(
70+
"databricks-bundle-lsp",
71+
"Databricks Bundle LSP",
72+
serverOptions,
73+
clientOptions
74+
);
75+
76+
await this.client.start();
77+
}
78+
79+
async stop(): Promise<void> {
80+
if (this.client) {
81+
try {
82+
await this.client.stop();
83+
} catch {
84+
// Client may already be stopped.
85+
}
86+
this.client = undefined;
87+
}
88+
}
89+
90+
dispose(): void {
91+
this.stop();
92+
}
93+
}

packages/databricks-vscode/src/extension.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import {
5050
BundleFileSet,
5151
registerBundleAutocompleteProvider,
5252
} from "./bundle";
53+
import {BundleLSPClient} from "./bundle/BundleLSPClient";
5354
import {showWhatsNewPopup} from "./whatsNewPopup";
5455
import {BundleValidateModel} from "./bundle/models/BundleValidateModel";
5556
import {ConfigModel} from "./configuration/models/ConfigModel";
@@ -890,6 +891,20 @@ export async function activate(
890891
);
891892
});
892893

894+
// Start the DABs LSP client for deployment-aware features (document links, hover).
895+
const bundleLSPClient = new BundleLSPClient(cli);
896+
context.subscriptions.push(bundleLSPClient);
897+
898+
const workspaceFolder = workspace.workspaceFolders?.[0]?.uri;
899+
if (workspaceFolder) {
900+
bundleLSPClient.start(workspaceFolder).catch((e) => {
901+
logging.NamedLogger.getOrCreate(Loggers.Extension).error(
902+
"Failed to start bundle LSP: ",
903+
e
904+
);
905+
});
906+
}
907+
893908
setDbnbCellLimits(workspaceFolderManager, connectionManager).catch((e) => {
894909
logging.NamedLogger.getOrCreate(Loggers.Extension).error(
895910
"Error while setting jupyter configs for parsing databricks notebooks",

yarn.lock

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3799,6 +3799,7 @@ __metadata:
37993799
ts-node: ^10.9.2
38003800
typescript: ^5.3.3
38013801
vsce: ^2.15.0
3802+
vscode-languageclient: ^9.0.1
38023803
wdio-video-reporter: ^5.1.4
38033804
wdio-vscode-service: ^6.0.2
38043805
winston: ^3.11.0
@@ -9520,6 +9521,15 @@ __metadata:
95209521
languageName: node
95219522
linkType: hard
95229523

9524+
"semver@npm:^7.3.7":
9525+
version: 7.7.4
9526+
resolution: "semver@npm:7.7.4"
9527+
bin:
9528+
semver: bin/semver.js
9529+
checksum: 9b4a6a58e98b9723fafcafa393c9d4e8edefaa60b8dfbe39e30892a3604cf1f45f52df9cfb1ae1a22b44c8b3d57fec8a9bb7b3e1645431587cb272399ede152e
9530+
languageName: node
9531+
linkType: hard
9532+
95239533
"semver@npm:^7.5.2, semver@npm:^7.5.4":
95249534
version: 7.5.4
95259535
resolution: "semver@npm:7.5.4"
@@ -10840,6 +10850,41 @@ __metadata:
1084010850
languageName: node
1084110851
linkType: hard
1084210852

10853+
"vscode-jsonrpc@npm:8.2.0":
10854+
version: 8.2.0
10855+
resolution: "vscode-jsonrpc@npm:8.2.0"
10856+
checksum: f302a01e59272adc1ae6494581fa31c15499f9278df76366e3b97b2236c7c53ebfc71efbace9041cfd2caa7f91675b9e56f2407871a1b3c7f760a2e2ee61484a
10857+
languageName: node
10858+
linkType: hard
10859+
10860+
"vscode-languageclient@npm:^9.0.1":
10861+
version: 9.0.1
10862+
resolution: "vscode-languageclient@npm:9.0.1"
10863+
dependencies:
10864+
minimatch: ^5.1.0
10865+
semver: ^7.3.7
10866+
vscode-languageserver-protocol: 3.17.5
10867+
checksum: ff30e5a9aac6726a88fe443fd631fe7e6130225299667c13162547f0a13ca2548d3f277d68cfb3ef6dc1810c048b2cf0e05024e1bcbd11982cd8acf681a67873
10868+
languageName: node
10869+
linkType: hard
10870+
10871+
"vscode-languageserver-protocol@npm:3.17.5":
10872+
version: 3.17.5
10873+
resolution: "vscode-languageserver-protocol@npm:3.17.5"
10874+
dependencies:
10875+
vscode-jsonrpc: 8.2.0
10876+
vscode-languageserver-types: 3.17.5
10877+
checksum: dfb42d276df5dfea728267885b99872ecff62f6c20448b8539fae71bb196b420f5351c5aca7c1047bf8fb1f89fa94a961dce2bc5bf7e726198f4be0bb86a1e71
10878+
languageName: node
10879+
linkType: hard
10880+
10881+
"vscode-languageserver-types@npm:3.17.5":
10882+
version: 3.17.5
10883+
resolution: "vscode-languageserver-types@npm:3.17.5"
10884+
checksum: 79b420e7576398d396579ca3a461c9ed70e78db4403cd28bbdf4d3ed2b66a2b4114031172e51fad49f0baa60a2180132d7cb2ea35aa3157d7af3c325528210ac
10885+
languageName: node
10886+
linkType: hard
10887+
1084310888
"vscode-uri@npm:^3.0.8":
1084410889
version: 3.0.8
1084510890
resolution: "vscode-uri@npm:3.0.8"

0 commit comments

Comments
 (0)