Skip to content

Commit

Permalink
feat: accept notifications for subdirectory deno.json files (#1034)
Browse files Browse the repository at this point in the history
  • Loading branch information
nayeemrmn committed Jan 24, 2024
1 parent 081a549 commit 605bc7a
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 47 deletions.
87 changes: 66 additions & 21 deletions client/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as tasks from "./tasks";
import { DenoTestController, TestingFeature } from "./testing";
import type {
DenoExtensionContext,
DidChangeDenoConfigurationParams,
DidUpgradeCheckParams,
TestCommandOptions,
} from "./types";
Expand All @@ -32,7 +33,7 @@ import * as semver from "semver";
import * as vscode from "vscode";
import { LanguageClient, ServerOptions } from "vscode-languageclient/node";
import type { Location, Position } from "vscode-languageclient/node";
import { getWorkspacesEnabledInfo } from "./enable";
import { getWorkspacesEnabledInfo, setupCheckConfig } from "./enable";
import { denoUpgradePromptAndExecute } from "./upgrade";

// deno-lint-ignore no-explicit-any
Expand Down Expand Up @@ -82,13 +83,15 @@ export function startLanguageServer(
if (extensionContext.client) {
const client = extensionContext.client;
extensionContext.client = undefined;
extensionContext.testController?.dispose();
extensionContext.testController = undefined;
for (const disposable of extensionContext.clientSubscriptions ?? []) {
disposable.dispose();
}
extensionContext.statusBar.refresh(extensionContext);
vscode.commands.executeCommand("setContext", ENABLEMENT_FLAG, false);
const timeoutMs = 10_000;
await client.stop(timeoutMs);
}
extensionContext.clientSubscriptions = [];

// Start a new language server
const command = await getDenoCommandPath();
Expand Down Expand Up @@ -151,34 +154,76 @@ export function startLanguageServer(
);
extensionContext.serverCapabilities = client.initializeResult?.capabilities;
extensionContext.statusBar.refresh(extensionContext);
context.subscriptions.push(extensionContext.client.onNotification(
"deno/didChangeDenoConfiguration",
() => {
extensionContext.tasksSidebar.refresh();
},
));
context.subscriptions.push(extensionContext.client.onNotification(
"deno/didUpgradeCheck",
(params: DidUpgradeCheckParams) => {
if (extensionContext.serverInfo) {
extensionContext.serverInfo.upgradeAvailable =
params.upgradeAvailable;
extensionContext.statusBar.refresh(extensionContext);
}
},
));

extensionContext.clientSubscriptions.push(
extensionContext.client.onNotification(
"deno/didUpgradeCheck",
(params: DidUpgradeCheckParams) => {
if (extensionContext.serverInfo) {
extensionContext.serverInfo.upgradeAvailable =
params.upgradeAvailable;
extensionContext.statusBar.refresh(extensionContext);
}
},
),
);

if (testingFeature.enabled) {
context.subscriptions.push(new DenoTestController(extensionContext));
extensionContext.clientSubscriptions.push(
new DenoTestController(extensionContext.client),
);
}

context.subscriptions.push(
extensionContext.clientSubscriptions.push(
client.onNotification(
registryState,
createRegistryStateHandler(),
),
);

// TODO(nayeemrmn): LSP version < 1.40.0 don't support the required API for
// "deno/didChangeDenoConfiguration". Remove this eventually.
if (semver.lt(extensionContext.serverInfo.version, "1.40.0")) {
extensionContext.scopesWithDenoJson = new Set();
extensionContext.clientSubscriptions.push(
extensionContext.client.onNotification(
"deno/didChangeDenoConfiguration",
() => {
extensionContext.tasksSidebar.refresh();
},
),
);
extensionContext.clientSubscriptions.push(
await setupCheckConfig(extensionContext),
);
} else {
const scopesWithDenoJson = new Set<string>();
extensionContext.scopesWithDenoJson = scopesWithDenoJson;
extensionContext.clientSubscriptions.push(
extensionContext.client.onNotification(
"deno/didChangeDenoConfiguration",
({ changes }: DidChangeDenoConfigurationParams) => {
let changedScopes = false;
for (const change of changes) {
if (change.type == "added") {
const scopePath = vscode.Uri.parse(change.scopeUri).fsPath;
scopesWithDenoJson.add(scopePath);
changedScopes = true;
} else if (change.type == "removed") {
const scopePath = vscode.Uri.parse(change.scopeUri).fsPath;
scopesWithDenoJson.delete(scopePath);
changedScopes = true;
}
}
if (changedScopes) {
extensionContext.tsApi?.refresh();
}
extensionContext.tasksSidebar.refresh();
},
),
);
}

extensionContext.tsApi.refresh();

if (
Expand Down
4 changes: 2 additions & 2 deletions client/src/enable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ export async function setupCheckConfig(
if (!uri) {
return;
}
extensionContext.scopesWithDenoJson = [];
extensionContext.scopesWithDenoJson = new Set();
if (
await exists(vscode.Uri.joinPath(uri, "./deno.json")) ||
await exists(vscode.Uri.joinPath(uri, "./deno.jsonc"))
) {
extensionContext.scopesWithDenoJson.push(uri.fsPath);
extensionContext.scopesWithDenoJson.add(uri.fsPath);
}
extensionContext.tsApi?.refresh();
}
Expand Down
20 changes: 12 additions & 8 deletions client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from "./constants";
import { DenoTextDocumentContentProvider, SCHEME } from "./content_provider";
import { DenoDebugConfigurationProvider } from "./debug_config_provider";
import { refreshEnableSettings, setupCheckConfig } from "./enable";
import { refreshEnableSettings } from "./enable";
import { DenoStatusBar } from "./status_bar";
import { activateTaskProvider } from "./tasks";
import { getTsApi } from "./ts_api";
Expand Down Expand Up @@ -175,18 +175,18 @@ export async function activate(
// Activate the task provider.
context.subscriptions.push(activateTaskProvider(extensionContext));

extensionContext.tsApi = getTsApi(() => ({
enableSettingsUnscoped: extensionContext.enableSettingsUnscoped,
enableSettingsByFolder: extensionContext.enableSettingsByFolder,
scopesWithDenoJson: extensionContext.scopesWithDenoJson,
}));
extensionContext.tsApi = getTsApi(() => {
return {
enableSettingsUnscoped: extensionContext.enableSettingsUnscoped,
enableSettingsByFolder: extensionContext.enableSettingsByFolder,
scopesWithDenoJson: Array.from(extensionContext.scopesWithDenoJson ?? []),
};
});

extensionContext.maxTsServerMemory =
vscode.workspace.getConfiguration(EXTENSION_NS).get("maxTsServerMemory") ??
null;
refreshEnableSettings(extensionContext);
extensionContext.scopesWithDenoJson = [];
context.subscriptions.push(await setupCheckConfig(extensionContext));

extensionContext.tasksSidebar = registerSidebar(
extensionContext,
Expand Down Expand Up @@ -235,6 +235,10 @@ export function deactivate(): Thenable<void> | undefined {

const client = extensionContext.client;
extensionContext.client = undefined;
for (const disposable of extensionContext.clientSubscriptions ?? []) {
disposable.dispose();
}
extensionContext.clientSubscriptions = undefined;
extensionContext.statusBar.refresh(extensionContext);
vscode.commands.executeCommand("setContext", ENABLEMENT_FLAG, false);
return client.stop();
Expand Down
2 changes: 1 addition & 1 deletion client/src/status_bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class DenoStatusBar {
// show only when "enable" is true and language server started
if (
extensionContext.client && extensionContext.serverInfo &&
(extensionContext.scopesWithDenoJson.length != 0 ||
(extensionContext.scopesWithDenoJson?.size ||
extensionContext.enableSettingsUnscoped.enable ||
extensionContext.enableSettingsUnscoped.enablePaths?.length ||
extensionContext.enableSettingsByFolder.find(([_, s]) =>
Expand Down
19 changes: 6 additions & 13 deletions client/src/testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ import {
testRunCancel,
testRunProgress,
} from "./lsp_extensions";
import type { DenoExtensionContext } from "./types";
import { assert } from "./util";

import * as vscode from "vscode";
import { FeatureState, MarkupKind } from "vscode-languageclient/node";
import type {
ClientCapabilities,
DocumentSelector,
LanguageClient,
MarkupContent,
ServerCapabilities,
StaticFeature,
Expand Down Expand Up @@ -136,19 +135,13 @@ export class DenoTestController implements vscode.Disposable {
#runCount = 0;
#runs = new Map<number, vscode.TestRun>();
#subscriptions: vscode.Disposable[] = [];
#testController: vscode.TestController;

constructor(extensionContext: DenoExtensionContext) {
const testController = extensionContext.testController =
this
.#testController =
vscode.tests
.createTestController("denoTestController", "Deno");
constructor(client: LanguageClient) {
const testController = vscode.tests.createTestController(
"denoTestController",
"Deno",
);
this.#subscriptions.push(testController);

const { client } = extensionContext;
assert(client);

const runHandler = async (
request: vscode.TestRunRequest,
cancellation: vscode.CancellationToken,
Expand Down
15 changes: 13 additions & 2 deletions client/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,21 @@ interface DenoExperimental {

export interface DenoExtensionContext {
client: LanguageClient | undefined;
clientSubscriptions: { dispose(): unknown }[] | undefined;
clientOptions: LanguageClientOptions;
serverInfo: DenoServerInfo | undefined;
/** The capabilities returned from the server. */
serverCapabilities:
| ServerCapabilities<DenoExperimental>
| undefined;
scopesWithDenoJson: Set<string> | undefined;
statusBar: DenoStatusBar;
testController: vscode.TestController | undefined;
tsApi: TsApi;
outputChannel: vscode.OutputChannel;
tasksSidebar: DenoTasksTreeDataProvider;
maxTsServerMemory: number | null;
enableSettingsUnscoped: EnableSettings;
enableSettingsByFolder: [string, EnableSettings][];
scopesWithDenoJson: string[];
}

export interface TestCommandOptions {
Expand All @@ -56,3 +56,14 @@ export interface UpgradeAvailable {
export interface DidUpgradeCheckParams {
upgradeAvailable: UpgradeAvailable | null;
}

export interface DenoConfigurationChangeEvent {
scopeUri: string;
fileUri: string;
type: "added" | "changed" | "removed";
configurationType: "denoJson" | "packageJson";
}

export interface DidChangeDenoConfigurationParams {
changes: DenoConfigurationChangeEvent[];
}

0 comments on commit 605bc7a

Please sign in to comment.