diff --git a/extensions/typescript-language-features/src/tsServer/api.ts b/extensions/typescript-language-features/src/tsServer/api.ts index 4a35ada0f24b4..2378bfb53f0f2 100644 --- a/extensions/typescript-language-features/src/tsServer/api.ts +++ b/extensions/typescript-language-features/src/tsServer/api.ts @@ -80,4 +80,8 @@ export class API { public lt(other: API): boolean { return !this.gte(other); } + + public isYarnPnp(): boolean { + return this.fullVersionString.includes('-sdk'); + } } diff --git a/extensions/typescript-language-features/src/tsServer/spawner.ts b/extensions/typescript-language-features/src/tsServer/spawner.ts index bc55ab4fdb304..543140dbab54e 100644 --- a/extensions/typescript-language-features/src/tsServer/spawner.ts +++ b/extensions/typescript-language-features/src/tsServer/spawner.ts @@ -271,7 +271,11 @@ export class TypeScriptServerSpawner { args.push('--noGetErrOnBackgroundUpdate'); - if (apiVersion.gte(API.v544) && configuration.useVsCodeWatcher) { + if ( + apiVersion.gte(API.v544) + && configuration.useVsCodeWatcher + && !apiVersion.isYarnPnp() // Disable for yarn pnp as it currently breaks with the VS Code watcher + ) { args.push('--canUseWatchEvents'); } diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index 78a77f23c9f0c..24742f99219fb 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -5,32 +5,32 @@ import * as path from 'path'; import * as vscode from 'vscode'; +import { ServiceConfigurationProvider, SyntaxServerConfiguration, TsServerLogLevel, TypeScriptServiceConfiguration, areServiceConfigurationsEqual } from './configuration/configuration'; +import * as fileSchemes from './configuration/fileSchemes'; +import { Schemes } from './configuration/schemes'; import { IExperimentationTelemetryReporter } from './experimentTelemetryReporter'; import { DiagnosticKind, DiagnosticsManager } from './languageFeatures/diagnostics'; -import * as Proto from './tsServer/protocol/protocol'; -import { EventName } from './tsServer/protocol/protocol.const'; +import { Logger } from './logging/logger'; +import { TelemetryProperties, TelemetryReporter, VSCodeTelemetryReporter } from './logging/telemetry'; +import Tracer from './logging/tracer'; +import { ProjectType, inferredProjectCompilerOptions } from './tsconfig'; import { API } from './tsServer/api'; import BufferSyncSupport from './tsServer/bufferSyncSupport'; import { OngoingRequestCancellerFactory } from './tsServer/cancellation'; import { ILogDirectoryProvider } from './tsServer/logDirectoryProvider'; +import { NodeVersionManager } from './tsServer/nodeManager'; import { TypeScriptPluginPathsProvider } from './tsServer/pluginPathsProvider'; +import { PluginManager, TypeScriptServerPlugin } from './tsServer/plugins'; +import * as Proto from './tsServer/protocol/protocol'; +import { EventName } from './tsServer/protocol/protocol.const'; import { ITypeScriptServer, TsServerLog, TsServerProcessFactory, TypeScriptServerExitEvent } from './tsServer/server'; import { TypeScriptServerError } from './tsServer/serverError'; import { TypeScriptServerSpawner } from './tsServer/spawner'; import { TypeScriptVersionManager } from './tsServer/versionManager'; import { ITypeScriptVersionProvider, TypeScriptVersion } from './tsServer/versionProvider'; import { ClientCapabilities, ClientCapability, ExecConfig, ITypeScriptServiceClient, ServerResponse, TypeScriptRequests } from './typescriptService'; -import { ServiceConfigurationProvider, SyntaxServerConfiguration, TsServerLogLevel, TypeScriptServiceConfiguration, areServiceConfigurationsEqual } from './configuration/configuration'; import { Disposable, DisposableStore, disposeAll } from './utils/dispose'; -import * as fileSchemes from './configuration/fileSchemes'; -import { Logger } from './logging/logger'; import { isWeb, isWebAndHasSharedArrayBuffers } from './utils/platform'; -import { PluginManager, TypeScriptServerPlugin } from './tsServer/plugins'; -import { TelemetryProperties, TelemetryReporter, VSCodeTelemetryReporter } from './logging/telemetry'; -import Tracer from './logging/tracer'; -import { ProjectType, inferredProjectCompilerOptions } from './tsconfig'; -import { Schemes } from './configuration/schemes'; -import { NodeVersionManager } from './tsServer/nodeManager'; export interface TsDiagnostics { @@ -463,7 +463,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType } */ this.logTelemetry('tsserver.error'); - this.serviceExited(false); + this.serviceExited(false, apiVersion); }); handle.onExit((data: TypeScriptServerExitEvent) => { @@ -484,7 +484,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType */ this.logTelemetry('tsserver.exitWithCode', { code: code ?? undefined, signal: signal ?? undefined }); - if (this.token !== mytoken) { // this is coming from an old process return; @@ -493,7 +492,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType if (handle.tsServerLog?.type === 'file') { this.info(`TSServer log file: ${handle.tsServerLog.uri.fsPath}`); } - this.serviceExited(!this.isRestarting); + this.serviceExited(!this.isRestarting, apiVersion); this.isRestarting = false; }); @@ -612,7 +611,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType }; } - private serviceExited(restart: boolean): void { + private serviceExited(restart: boolean, tsVersion: API): void { this.resetWatchers(); this.loadingIndicator.reset(); @@ -686,17 +685,34 @@ export default class TypeScriptServiceClient extends Disposable implements IType this._isPromptingAfterCrash = true; } - prompt?.then(item => { + prompt?.then(async item => { this._isPromptingAfterCrash = false; if (item === reportIssueItem) { + const minModernTsVersion = this.versionProvider.bundledVersion.apiVersion; - if ( + // Don't allow reporting issues using the PnP patched version of TS Server + if (tsVersion.isYarnPnp()) { + const reportIssue: vscode.MessageItem = { + title: vscode.l10n.t("Report issue against Yarn PnP"), + }; + const response = await vscode.window.showWarningMessage( + vscode.l10n.t("Please report an issue against Yarn PnP"), + { + modal: true, + detail: vscode.l10n.t("The workspace is using a version of the TypeScript Server that has been patched by Yarn PnP. This patching is a common source of bugs."), + }, + reportIssue); + + if (response === reportIssue) { + vscode.env.openExternal(vscode.Uri.parse('https://github.com/yarnpkg/berry/issues')); + } + } + // Don't allow reporting issues with old TS versions + else if ( minModernTsVersion && - previousState.type === ServerState.Type.Errored && - previousState.error instanceof TypeScriptServerError && - previousState.error.version.apiVersion?.lt(minModernTsVersion) + tsVersion.lt(minModernTsVersion) ) { vscode.window.showWarningMessage( vscode.l10n.t("Please update your TypeScript version"), @@ -704,7 +720,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType modal: true, detail: vscode.l10n.t( "The workspace is using an old version of TypeScript ({0}).\n\nBefore reporting an issue, please update the workspace to use TypeScript {1} or newer to make sure the bug has not already been fixed.", - previousState.error.version.apiVersion.displayName, + tsVersion.displayName, minModernTsVersion.displayName), }); } else {