mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-24 12:19:20 +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
|
* @param enable Whether to enable or disable TypeScript Go
|
||||||
*/
|
*/
|
||||||
async function updateTsgoSetting(enable: boolean): Promise<void> {
|
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
|
// Error if the TypeScript Go extension is not installed with a button to open the GitHub repo
|
||||||
if (!tsgoExtension) {
|
if (!tsgoExtension) {
|
||||||
const selection = await vscode.window.showErrorMessage(
|
const selection = await vscode.window.showErrorMessage(
|
||||||
|
|||||||
@@ -25,27 +25,12 @@ import { onCaseInsensitiveFileSystem } from './utils/fs.electron';
|
|||||||
import { Lazy } from './utils/lazy';
|
import { Lazy } from './utils/lazy';
|
||||||
import { getPackageInfo } from './utils/packageInfo';
|
import { getPackageInfo } from './utils/packageInfo';
|
||||||
import * as temp from './utils/temp.electron';
|
import * as temp from './utils/temp.electron';
|
||||||
|
import { conditionalRegistration, requireGlobalConfiguration } from './languageFeatures/util/dependentRegistration';
|
||||||
|
import { DisposableStore } from './utils/dispose';
|
||||||
|
|
||||||
export function activate(
|
export function activate(
|
||||||
context: vscode.ExtensionContext
|
context: vscode.ExtensionContext
|
||||||
): Api {
|
): 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();
|
const pluginManager = new PluginManager();
|
||||||
context.subscriptions.push(pluginManager);
|
context.subscriptions.push(pluginManager);
|
||||||
|
|
||||||
@@ -55,9 +40,6 @@ export function activate(
|
|||||||
const logDirectoryProvider = new NodeLogDirectoryProvider(context);
|
const logDirectoryProvider = new NodeLogDirectoryProvider(context);
|
||||||
const versionProvider = new DiskTypeScriptVersionProvider();
|
const versionProvider = new DiskTypeScriptVersionProvider();
|
||||||
|
|
||||||
const activeJsTsEditorTracker = new ActiveJsTsEditorTracker();
|
|
||||||
context.subscriptions.push(activeJsTsEditorTracker);
|
|
||||||
|
|
||||||
let experimentTelemetryReporter: IExperimentationTelemetryReporter | undefined;
|
let experimentTelemetryReporter: IExperimentationTelemetryReporter | undefined;
|
||||||
const packageInfo = getPackageInfo(context);
|
const packageInfo = getPackageInfo(context);
|
||||||
if (packageInfo) {
|
if (packageInfo) {
|
||||||
@@ -71,34 +53,55 @@ export function activate(
|
|||||||
new ExperimentationService(experimentTelemetryReporter, id, version, context.globalState);
|
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(), {
|
const commandManager = disposables.add(new CommandManager());
|
||||||
pluginManager,
|
commandManager.register(new DisableTsgoCommand());
|
||||||
commandManager,
|
|
||||||
logDirectoryProvider,
|
|
||||||
cancellerFactory: nodeRequestCancellerFactory,
|
|
||||||
versionProvider,
|
|
||||||
processFactory: new ElectronServiceProcessFactory(),
|
|
||||||
activeJsTsEditorTracker,
|
|
||||||
serviceConfigurationProvider: new ElectronServiceConfigurationProvider(),
|
|
||||||
experimentTelemetryReporter,
|
|
||||||
logger,
|
|
||||||
}, item => {
|
|
||||||
onCompletionAccepted.fire(item);
|
|
||||||
});
|
|
||||||
|
|
||||||
registerBaseCommands(commandManager, lazyClientHost, pluginManager, activeJsTsEditorTracker);
|
return disposables;
|
||||||
|
}, () => {
|
||||||
|
// Normal registration path
|
||||||
|
const disposables = new DisposableStore();
|
||||||
|
|
||||||
import('./task/taskProvider').then(module => {
|
const commandManager = disposables.add(new CommandManager());
|
||||||
context.subscriptions.push(module.register(new Lazy(() => lazyClientHost.value.serviceClient)));
|
const activeJsTsEditorTracker = disposables.add(new ActiveJsTsEditorTracker());
|
||||||
});
|
|
||||||
|
|
||||||
import('./languageFeatures/tsconfig').then(module => {
|
const lazyClientHost = createLazyClientHost(context, onCaseInsensitiveFileSystem(), {
|
||||||
context.subscriptions.push(module.register());
|
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);
|
return getExtensionApi(onCompletionAccepted.event, pluginManager);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,15 @@ export class Condition extends Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ConditionalRegistration {
|
class ConditionalRegistration {
|
||||||
private registration: vscode.Disposable | undefined = undefined;
|
private state?: {
|
||||||
|
readonly enabled: boolean;
|
||||||
|
readonly registration: vscode.Disposable | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private readonly conditions: readonly Condition[],
|
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) {
|
for (const condition of conditions) {
|
||||||
condition.onDidChange(() => this.update());
|
condition.onDidChange(() => this.update());
|
||||||
@@ -47,17 +51,22 @@ class ConditionalRegistration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
this.registration?.dispose();
|
this.state?.registration?.dispose();
|
||||||
this.registration = undefined;
|
this.state = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private update() {
|
private update() {
|
||||||
const enabled = this.conditions.every(condition => condition.value);
|
const enabled = this.conditions.every(condition => condition.value);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
this.registration ??= this.doRegister();
|
if (!this.state?.enabled) {
|
||||||
|
this.state?.registration?.dispose();
|
||||||
|
this.state = { enabled: true, registration: this.doRegister() };
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.registration?.dispose();
|
if (this.state?.enabled || !this.state) {
|
||||||
this.registration = undefined;
|
this.state?.registration?.dispose();
|
||||||
|
this.state = { enabled: false, registration: this.elseDoRegister?.() };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,8 +74,9 @@ class ConditionalRegistration {
|
|||||||
export function conditionalRegistration(
|
export function conditionalRegistration(
|
||||||
conditions: readonly Condition[],
|
conditions: readonly Condition[],
|
||||||
doRegister: () => vscode.Disposable,
|
doRegister: () => vscode.Disposable,
|
||||||
|
elseDoRegister?: () => vscode.Disposable
|
||||||
): vscode.Disposable {
|
): vscode.Disposable {
|
||||||
return new ConditionalRegistration(conditions, doRegister);
|
return new ConditionalRegistration(conditions, doRegister, elseDoRegister);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function requireMinVersion(
|
export function requireMinVersion(
|
||||||
|
|||||||
@@ -38,16 +38,12 @@ export function createLazyClientHost(
|
|||||||
onCompletionAccepted: (item: vscode.CompletionItem) => void,
|
onCompletionAccepted: (item: vscode.CompletionItem) => void,
|
||||||
): Lazy<TypeScriptServiceClientHost> {
|
): Lazy<TypeScriptServiceClientHost> {
|
||||||
return new Lazy(() => {
|
return new Lazy(() => {
|
||||||
const clientHost = new TypeScriptServiceClientHost(
|
return new TypeScriptServiceClientHost(
|
||||||
standardLanguageDescriptions,
|
standardLanguageDescriptions,
|
||||||
context,
|
context,
|
||||||
onCaseInsensitiveFileSystem,
|
onCaseInsensitiveFileSystem,
|
||||||
services,
|
services,
|
||||||
onCompletionAccepted);
|
onCompletionAccepted);
|
||||||
|
|
||||||
context.subscriptions.push(clientHost);
|
|
||||||
|
|
||||||
return clientHost;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ interface WatchEvent {
|
|||||||
|
|
||||||
export default class TypeScriptServiceClient extends Disposable implements ITypeScriptServiceClient {
|
export default class TypeScriptServiceClient extends Disposable implements ITypeScriptServiceClient {
|
||||||
|
|
||||||
|
|
||||||
private readonly _onReady?: { promise: Promise<void>; resolve: () => void; reject: () => void };
|
private readonly _onReady?: { promise: Promise<void>; resolve: () => void; reject: () => void };
|
||||||
private _configuration: TypeScriptServiceConfiguration;
|
private _configuration: TypeScriptServiceConfiguration;
|
||||||
private readonly pluginPathsProvider: TypeScriptPluginPathsProvider;
|
private readonly pluginPathsProvider: TypeScriptPluginPathsProvider;
|
||||||
@@ -632,6 +631,10 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||||||
|
|
||||||
this.serverState = ServerState.None;
|
this.serverState = ServerState.None;
|
||||||
|
|
||||||
|
if (this.isDisposed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (restart) {
|
if (restart) {
|
||||||
const diff = Date.now() - this.lastStart;
|
const diff = Date.now() - this.lastStart;
|
||||||
this.numberRestarts++;
|
this.numberRestarts++;
|
||||||
|
|||||||
@@ -44,4 +44,8 @@ export class Lazy<T> {
|
|||||||
* Get the wrapped value without forcing evaluation.
|
* Get the wrapped value without forcing evaluation.
|
||||||
*/
|
*/
|
||||||
get rawValue(): T | undefined { return this._value; }
|
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