Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not start TypeSpec Language Server when there is no workspace opened #5413

Merged
merged 25 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
09b57b7
start lsp only when workspace opened
RodgeFu Dec 19, 2024
827c2cf
add changelog
RodgeFu Dec 19, 2024
a53c955
refine message and error handling
RodgeFu Dec 20, 2024
43c5ddc
Merge remote-tracking branch 'upstream/main' into no-lsp-error-withou…
RodgeFu Dec 20, 2024
87a3c92
small update
RodgeFu Dec 21, 2024
b4bdba2
some update
RodgeFu Dec 21, 2024
e06b331
fix a bug
RodgeFu Dec 21, 2024
b7fdac7
refine some word
RodgeFu Dec 21, 2024
c59c0f6
Merge branch 'main' into no-lsp-error-without-workspace
RodgeFu Dec 21, 2024
b7b3d22
improve some notification and log
RodgeFu Dec 24, 2024
d6770d9
Merge remote-tracking branch 'refs/remotes/origin/no-lsp-error-withou…
RodgeFu Dec 24, 2024
1654547
add changelog of compiler
RodgeFu Dec 24, 2024
2798dec
fix linter error
RodgeFu Dec 24, 2024
173f31c
Merge remote-tracking branch 'upstream/main' into no-lsp-error-withou…
RodgeFu Dec 24, 2024
a65905e
refine some log text
RodgeFu Dec 24, 2024
cba025b
fix a bug
RodgeFu Dec 28, 2024
6677017
Merge branch 'main' into no-lsp-error-without-workspace
RodgeFu Dec 30, 2024
8d63ce9
Merge remote-tracking branch 'upstream/main' into no-lsp-error-withou…
RodgeFu Jan 2, 2025
2330ade
Merge remote-tracking branch 'refs/remotes/origin/no-lsp-error-withou…
RodgeFu Jan 2, 2025
1abc301
refine text and link per PM's requirement
RodgeFu Jan 2, 2025
47967ea
Merge remote-tracking branch 'upstream/main' into no-lsp-error-withou…
RodgeFu Jan 3, 2025
4ec666f
separate the change in compiler which is not related
RodgeFu Jan 3, 2025
5f0c05b
update changelog
RodgeFu Jan 3, 2025
8e1740a
Merge remote-tracking branch 'upstream/main' into no-lsp-error-withou…
RodgeFu Jan 3, 2025
3295fe3
handle no workspace case for start lsp
RodgeFu Jan 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: fix
packages:
- typespec-vscode
---

Do not start TypeSpec Language Server when there is no workspace opened
35 changes: 21 additions & 14 deletions packages/typespec-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ export async function activate(context: ExtensionContext) {
async (args: RestartServerCommandArgs | undefined): Promise<TspLanguageClient> => {
return vscode.window.withProgress(
{
title: "Restarting TypeSpec language service...",
title: args?.notificationMessage ?? "Restarting TypeSpec language service...",
location: vscode.ProgressLocation.Notification,
},
async () => {
if (args?.forceRecreate === true) {
logger.info("Forcing to recreate TypeSpec LSP server...");
return await recreateLSPClient(context, args?.popupRecreateLspError);
return await recreateLSPClient(context);
}
if (client && client.state === State.Running) {
await client.restart();
Expand All @@ -65,7 +65,7 @@ export async function activate(context: ExtensionContext) {
logger.info(
"TypeSpec LSP server is not running which is not expected, try to recreate and start...",
);
return recreateLSPClient(context, args?.popupRecreateLspError);
return recreateLSPClient(context);
}
},
);
Expand Down Expand Up @@ -97,26 +97,33 @@ export async function activate(context: ExtensionContext) {
}),
);

return await vscode.window.withProgress(
{
title: "Launching TypeSpec language service...",
location: vscode.ProgressLocation.Notification,
},
async () => {
await recreateLSPClient(context);
},
);
// Only try to start language server when some workspace has been opened
// because the LanguageClient class will popup error notification in vscode directly if failing to start
// which will be confusing to user if no workspace is opened (i.e. in Create TypeSpec project scenario)
if ((vscode.workspace.workspaceFolders?.length ?? 0) > 0) {
RodgeFu marked this conversation as resolved.
Show resolved Hide resolved
return await vscode.window.withProgress(
{
title: "Launching TypeSpec language service...",
location: vscode.ProgressLocation.Notification,
},
async () => {
await recreateLSPClient(context);
},
);
} else {
logger.info("No workspace opened, Skip starting TypeSpec language service.");
}
}

export async function deactivate() {
await client?.stop();
}

async function recreateLSPClient(context: ExtensionContext, showPopupWhenError?: boolean) {
async function recreateLSPClient(context: ExtensionContext) {
logger.info("Recreating TypeSpec LSP server...");
const oldClient = client;
client = await TspLanguageClient.create(context, outputChannel);
await oldClient?.stop();
await client.start(showPopupWhenError ?? (vscode.workspace.workspaceFolders?.length ?? 0) > 0);
await client.start();
return client;
}
7 changes: 4 additions & 3 deletions packages/typespec-vscode/src/tsp-language-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,10 @@ export class TspLanguageClient {
}
}

async start(showPopupWhenError: boolean): Promise<void> {
async start(): Promise<void> {
try {
if (this.client.needsStart()) {
// please be aware that this method would popup error notification in vscode directly
await this.client.start();
logger.info("TypeSpec server started");
} else {
Expand All @@ -162,13 +163,13 @@ export class TspLanguageClient {
" - TypeSpec server path is configured with https://github.com/microsoft/typespec#installing-vs-code-extension.",
].join("\n"),
[],
{ showOutput: false, showPopup: showPopupWhenError },
{ showOutput: false, showPopup: true },
);
logger.error("Error detail", [e]);
} else {
logger.error("Unexpected error when starting TypeSpec server", [e], {
showOutput: false,
showPopup: showPopupWhenError,
showPopup: true,
});
}
}
Expand Down
26 changes: 25 additions & 1 deletion packages/typespec-vscode/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,36 @@ export interface InstallGlobalCliCommandArgs {
confirm: boolean;
confirmTitle?: string;
confirmPlaceholder?: string;
/**
* set to true to disable popup notification and show output channel when running the command
*/
silentMode?: boolean;
}

export interface RestartServerCommandArgs {
/**
* whether to recreate TspLanguageClient instead of just restarting it
*/
forceRecreate: boolean;
popupRecreateLspError: boolean;
notificationMessage?: string;
}

export const enum ResultCode {
Success = "success",
Fail = "fail",
Cancelled = "cancelled",
Timeout = "timeout",
}

interface SuccessResult<T> {
code: ResultCode.Success;
value: T;
details?: any;
}

interface UnsuccessResult {
code: ResultCode.Fail | ResultCode.Cancelled | ResultCode.Timeout;
details?: any;
}

export type Result<T> = SuccessResult<T> | UnsuccessResult;
9 changes: 5 additions & 4 deletions packages/typespec-vscode/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CancellationToken } from "vscode";
import { Executable } from "vscode-languageclient/node.js";
import logger from "./log/logger.js";
import { isUrl } from "./path-utils.js";
import { ResultCode } from "./types.js";

export async function isFile(path: string) {
try {
Expand Down Expand Up @@ -278,8 +279,8 @@ export function spawnExecution(
}

/**
* if the operation is cancelled, the promise will be rejected with reason==="cancelled"
* if the operation is timeout, the promise will be rejected with reason==="timeout"
* if the operation is cancelled, the promise will be rejected with {@link ResultCode.Cancelled}
* if the operation is timeout, the promise will be rejected with {@link ResultCode.Timeout}
*
* @param action
* @param token
Expand All @@ -293,10 +294,10 @@ export function createPromiseWithCancelAndTimeout<T>(
) {
return new Promise<T>((resolve, reject) => {
token.onCancellationRequested(() => {
reject("cancelled");
reject(ResultCode.Cancelled);
});
setTimeout(() => {
reject("timeout");
reject(ResultCode.Timeout);
}, timeoutInMs);
action.then(resolve, reject);
});
Expand Down
Loading
Loading