mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-23 11:49:38 +00:00
Don't require restart when switching to TS native
For #266087 Dynamically registers / unregisters the language features
This commit is contained in:
@@ -27,7 +27,7 @@ export class DisableTsgoCommand implements Command {
|
||||
* @param enable Whether to enable or disable TypeScript Go
|
||||
*/
|
||||
async function updateTsgoSetting(enable: boolean): Promise<void> {
|
||||
const tsgoExtension = vscode.extensions.getExtension('typescript.typescript-lsp');
|
||||
const tsgoExtension = vscode.extensions.getExtension('typescriptteam.native-preview');
|
||||
// Error if the TypeScript Go extension is not installed with a button to open the GitHub repo
|
||||
if (!tsgoExtension) {
|
||||
const selection = await vscode.window.showErrorMessage(
|
||||
|
||||
@@ -25,27 +25,12 @@ import { onCaseInsensitiveFileSystem } from './utils/fs.electron';
|
||||
import { Lazy } from './utils/lazy';
|
||||
import { getPackageInfo } from './utils/packageInfo';
|
||||
import * as temp from './utils/temp.electron';
|
||||
import { conditionalRegistration, requireGlobalConfiguration } from './languageFeatures/util/dependentRegistration';
|
||||
import { DisposableStore } from './utils/dispose';
|
||||
|
||||
export function activate(
|
||||
context: vscode.ExtensionContext
|
||||
): Api {
|
||||
const commandManager = new CommandManager();
|
||||
context.subscriptions.push(commandManager);
|
||||
|
||||
// Disable extension if using the experimental TypeScript Go extension
|
||||
const config = vscode.workspace.getConfiguration('typescript');
|
||||
const useTsgo = config.get<boolean>('experimental.useTsgo', false);
|
||||
|
||||
if (useTsgo) {
|
||||
commandManager.register(new DisableTsgoCommand());
|
||||
// Return a no-op API when disabled
|
||||
return {
|
||||
getAPI() {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const pluginManager = new PluginManager();
|
||||
context.subscriptions.push(pluginManager);
|
||||
|
||||
@@ -55,9 +40,6 @@ export function activate(
|
||||
const logDirectoryProvider = new NodeLogDirectoryProvider(context);
|
||||
const versionProvider = new DiskTypeScriptVersionProvider();
|
||||
|
||||
const activeJsTsEditorTracker = new ActiveJsTsEditorTracker();
|
||||
context.subscriptions.push(activeJsTsEditorTracker);
|
||||
|
||||
let experimentTelemetryReporter: IExperimentationTelemetryReporter | undefined;
|
||||
const packageInfo = getPackageInfo(context);
|
||||
if (packageInfo) {
|
||||
@@ -71,34 +53,55 @@ export function activate(
|
||||
new ExperimentationService(experimentTelemetryReporter, id, version, context.globalState);
|
||||
}
|
||||
|
||||
const logger = new Logger();
|
||||
context.subscriptions.push(conditionalRegistration([
|
||||
requireGlobalConfiguration('typescript', 'experimental.useTsgo'),
|
||||
], () => {
|
||||
// TSGO. Only register a small set of features that don't use TS Server
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
const lazyClientHost = createLazyClientHost(context, onCaseInsensitiveFileSystem(), {
|
||||
pluginManager,
|
||||
commandManager,
|
||||
logDirectoryProvider,
|
||||
cancellerFactory: nodeRequestCancellerFactory,
|
||||
versionProvider,
|
||||
processFactory: new ElectronServiceProcessFactory(),
|
||||
activeJsTsEditorTracker,
|
||||
serviceConfigurationProvider: new ElectronServiceConfigurationProvider(),
|
||||
experimentTelemetryReporter,
|
||||
logger,
|
||||
}, item => {
|
||||
onCompletionAccepted.fire(item);
|
||||
});
|
||||
const commandManager = disposables.add(new CommandManager());
|
||||
commandManager.register(new DisableTsgoCommand());
|
||||
|
||||
registerBaseCommands(commandManager, lazyClientHost, pluginManager, activeJsTsEditorTracker);
|
||||
return disposables;
|
||||
}, () => {
|
||||
// Normal registration path
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
import('./task/taskProvider').then(module => {
|
||||
context.subscriptions.push(module.register(new Lazy(() => lazyClientHost.value.serviceClient)));
|
||||
});
|
||||
const commandManager = disposables.add(new CommandManager());
|
||||
const activeJsTsEditorTracker = disposables.add(new ActiveJsTsEditorTracker());
|
||||
|
||||
import('./languageFeatures/tsconfig').then(module => {
|
||||
context.subscriptions.push(module.register());
|
||||
});
|
||||
const lazyClientHost = createLazyClientHost(context, onCaseInsensitiveFileSystem(), {
|
||||
pluginManager,
|
||||
commandManager,
|
||||
logDirectoryProvider,
|
||||
cancellerFactory: nodeRequestCancellerFactory,
|
||||
versionProvider,
|
||||
processFactory: new ElectronServiceProcessFactory(),
|
||||
activeJsTsEditorTracker,
|
||||
serviceConfigurationProvider: new ElectronServiceConfigurationProvider(),
|
||||
experimentTelemetryReporter,
|
||||
logger: new Logger(),
|
||||
}, item => {
|
||||
onCompletionAccepted.fire(item);
|
||||
}).map(clientHost => {
|
||||
return disposables.add(clientHost);
|
||||
});
|
||||
|
||||
context.subscriptions.push(lazilyActivateClient(lazyClientHost, pluginManager, activeJsTsEditorTracker));
|
||||
// Register features
|
||||
registerBaseCommands(commandManager, lazyClientHost, pluginManager, activeJsTsEditorTracker);
|
||||
|
||||
import('./task/taskProvider').then(module => {
|
||||
disposables.add(module.register(new Lazy(() => lazyClientHost.value.serviceClient)));
|
||||
});
|
||||
|
||||
import('./languageFeatures/tsconfig').then(module => {
|
||||
disposables.add(module.register());
|
||||
});
|
||||
|
||||
disposables.add(lazilyActivateClient(lazyClientHost, pluginManager, activeJsTsEditorTracker));
|
||||
|
||||
return disposables;
|
||||
},));
|
||||
|
||||
return getExtensionApi(onCompletionAccepted.event, pluginManager);
|
||||
}
|
||||
|
||||
@@ -34,11 +34,15 @@ export class Condition extends Disposable {
|
||||
}
|
||||
|
||||
class ConditionalRegistration {
|
||||
private registration: vscode.Disposable | undefined = undefined;
|
||||
private state?: {
|
||||
readonly enabled: boolean;
|
||||
readonly registration: vscode.Disposable | undefined;
|
||||
};
|
||||
|
||||
public constructor(
|
||||
private readonly conditions: readonly Condition[],
|
||||
private readonly doRegister: () => vscode.Disposable
|
||||
private readonly doRegister: () => vscode.Disposable,
|
||||
private readonly elseDoRegister?: () => vscode.Disposable
|
||||
) {
|
||||
for (const condition of conditions) {
|
||||
condition.onDidChange(() => this.update());
|
||||
@@ -47,17 +51,22 @@ class ConditionalRegistration {
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this.registration?.dispose();
|
||||
this.registration = undefined;
|
||||
this.state?.registration?.dispose();
|
||||
this.state = undefined;
|
||||
}
|
||||
|
||||
private update() {
|
||||
const enabled = this.conditions.every(condition => condition.value);
|
||||
if (enabled) {
|
||||
this.registration ??= this.doRegister();
|
||||
if (!this.state?.enabled) {
|
||||
this.state?.registration?.dispose();
|
||||
this.state = { enabled: true, registration: this.doRegister() };
|
||||
}
|
||||
} else {
|
||||
this.registration?.dispose();
|
||||
this.registration = undefined;
|
||||
if (this.state?.enabled || !this.state) {
|
||||
this.state?.registration?.dispose();
|
||||
this.state = { enabled: false, registration: this.elseDoRegister?.() };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,8 +74,9 @@ class ConditionalRegistration {
|
||||
export function conditionalRegistration(
|
||||
conditions: readonly Condition[],
|
||||
doRegister: () => vscode.Disposable,
|
||||
elseDoRegister?: () => vscode.Disposable
|
||||
): vscode.Disposable {
|
||||
return new ConditionalRegistration(conditions, doRegister);
|
||||
return new ConditionalRegistration(conditions, doRegister, elseDoRegister);
|
||||
}
|
||||
|
||||
export function requireMinVersion(
|
||||
|
||||
@@ -38,16 +38,12 @@ export function createLazyClientHost(
|
||||
onCompletionAccepted: (item: vscode.CompletionItem) => void,
|
||||
): Lazy<TypeScriptServiceClientHost> {
|
||||
return new Lazy(() => {
|
||||
const clientHost = new TypeScriptServiceClientHost(
|
||||
return new TypeScriptServiceClientHost(
|
||||
standardLanguageDescriptions,
|
||||
context,
|
||||
onCaseInsensitiveFileSystem,
|
||||
services,
|
||||
onCompletionAccepted);
|
||||
|
||||
context.subscriptions.push(clientHost);
|
||||
|
||||
return clientHost;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,6 @@ interface WatchEvent {
|
||||
|
||||
export default class TypeScriptServiceClient extends Disposable implements ITypeScriptServiceClient {
|
||||
|
||||
|
||||
private readonly _onReady?: { promise: Promise<void>; resolve: () => void; reject: () => void };
|
||||
private _configuration: TypeScriptServiceConfiguration;
|
||||
private readonly pluginPathsProvider: TypeScriptPluginPathsProvider;
|
||||
@@ -632,6 +631,10 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
|
||||
this.serverState = ServerState.None;
|
||||
|
||||
if (this.isDisposed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (restart) {
|
||||
const diff = Date.now() - this.lastStart;
|
||||
this.numberRestarts++;
|
||||
|
||||
@@ -44,4 +44,8 @@ export class Lazy<T> {
|
||||
* Get the wrapped value without forcing evaluation.
|
||||
*/
|
||||
get rawValue(): T | undefined { return this._value; }
|
||||
|
||||
map<R>(fn: (value: T) => R): Lazy<R> {
|
||||
return new Lazy(() => fn(this.value));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user