mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-24 18:49:00 +01:00
Introduce basic lazy type to encapsulate the idea of a lazy value
This commit is contained in:
@@ -7,16 +7,17 @@ import * as vscode from 'vscode';
|
||||
|
||||
import { TypeScriptServiceClientHost } from './typescriptMain';
|
||||
import { Command } from './utils/commandManager';
|
||||
import { Lazy } from './utils/lazy';
|
||||
|
||||
export class ReloadTypeScriptProjectsCommand implements Command {
|
||||
public readonly id = 'typescript.reloadProjects';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost
|
||||
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
this.lazyClientHost().reloadProjects();
|
||||
this.lazyClientHost.value.reloadProjects();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +25,11 @@ export class ReloadJavaScriptProjectsCommand implements Command {
|
||||
public readonly id = 'javascript.reloadProjects';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost
|
||||
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
this.lazyClientHost().reloadProjects();
|
||||
this.lazyClientHost.value.reloadProjects();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,11 +37,11 @@ export class SelectTypeScriptVersionCommand implements Command {
|
||||
public readonly id = 'typescript.selectTypeScriptVersion';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost
|
||||
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
this.lazyClientHost().serviceClient.onVersionStatusClicked();
|
||||
this.lazyClientHost.value.serviceClient.onVersionStatusClicked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,11 +49,11 @@ export class OpenTsServerLogCommand implements Command {
|
||||
public readonly id = 'typescript.openTsServerLog';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost
|
||||
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
this.lazyClientHost().serviceClient.openTsServerLogFile();
|
||||
this.lazyClientHost.value.serviceClient.openTsServerLogFile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,11 +61,11 @@ export class RestartTsServerCommand implements Command {
|
||||
public readonly id = 'typescript.restartTsServer';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost
|
||||
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
this.lazyClientHost().serviceClient.restartTsServer();
|
||||
this.lazyClientHost.value.serviceClient.restartTsServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,13 +73,13 @@ export class TypeScriptGoToProjectConfigCommand implements Command {
|
||||
public readonly id = 'typescript.goToProjectConfig';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost,
|
||||
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>,
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor) {
|
||||
this.lazyClientHost().goToProjectConfig(true, editor.document.uri);
|
||||
this.lazyClientHost.value.goToProjectConfig(true, editor.document.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,13 +88,13 @@ export class JavaScriptGoToProjectConfigCommand implements Command {
|
||||
public readonly id = 'javascript.goToProjectConfig';
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClientHost: () => TypeScriptServiceClientHost,
|
||||
private readonly lazyClientHost: Lazy<TypeScriptServiceClientHost>,
|
||||
) { }
|
||||
|
||||
public execute() {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (editor) {
|
||||
this.lazyClientHost().goToProjectConfig(false, editor.document.uri);
|
||||
this.lazyClientHost.value.goToProjectConfig(false, editor.document.uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import * as languageModeIds from './utils/languageModeIds';
|
||||
import * as languageConfigurations from './utils/languageConfigurations';
|
||||
import { standardLanguageDescriptions } from './utils/languageDescription';
|
||||
import ManagedFileContextManager from './utils/managedFileContext';
|
||||
import { lazy, Lazy } from './utils/lazy';
|
||||
|
||||
export function activate(
|
||||
context: vscode.ExtensionContext
|
||||
@@ -26,9 +27,9 @@ export function activate(
|
||||
|
||||
const lazyClientHost = createLazyClientHost(context, plugins, commandManager);
|
||||
|
||||
context.subscriptions.push(new ManagedFileContextManager(resource => lazyClientHost().serviceClient.normalizePath(resource)));
|
||||
context.subscriptions.push(new ManagedFileContextManager(resource => lazyClientHost.value.serviceClient.normalizePath(resource)));
|
||||
registerCommands(commandManager, lazyClientHost);
|
||||
context.subscriptions.push(new TypeScriptTaskProviderManager(() => lazyClientHost().serviceClient));
|
||||
context.subscriptions.push(new TypeScriptTaskProviderManager(lazyClientHost.map(x => x.serviceClient)));
|
||||
context.subscriptions.push(vscode.languages.setLanguageConfiguration(languageModeIds.jsxTags, languageConfigurations.jsxTags));
|
||||
|
||||
|
||||
@@ -37,7 +38,8 @@ export function activate(
|
||||
if (supportedLanguage.indexOf(textDocument.languageId) >= 0) {
|
||||
openListener.dispose();
|
||||
// Force activation
|
||||
void lazyClientHost();
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
void lazyClientHost.value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -54,26 +56,23 @@ function createLazyClientHost(
|
||||
context: vscode.ExtensionContext,
|
||||
plugins: TypeScriptServerPlugin[],
|
||||
commandManager: CommandManager
|
||||
) {
|
||||
let clientHost: TypeScriptServiceClientHost | undefined = undefined;
|
||||
return () => {
|
||||
if (!clientHost) {
|
||||
clientHost = new TypeScriptServiceClientHost(standardLanguageDescriptions, context.workspaceState, plugins, commandManager);
|
||||
context.subscriptions.push(clientHost);
|
||||
const host = clientHost;
|
||||
clientHost.serviceClient.onReady().then(() => {
|
||||
context.subscriptions.push(ProjectStatus.create(host.serviceClient, host.serviceClient.telemetryReporter, path => new Promise<boolean>(resolve => setTimeout(() => resolve(host.handles(path)), 750)), context.workspaceState));
|
||||
}, () => {
|
||||
// Nothing to do here. The client did show a message;
|
||||
});
|
||||
}
|
||||
): Lazy<TypeScriptServiceClientHost> {
|
||||
return lazy(() => {
|
||||
const clientHost = new TypeScriptServiceClientHost(standardLanguageDescriptions, context.workspaceState, plugins, commandManager);
|
||||
context.subscriptions.push(clientHost);
|
||||
const host = clientHost;
|
||||
clientHost.serviceClient.onReady().then(() => {
|
||||
context.subscriptions.push(ProjectStatus.create(host.serviceClient, host.serviceClient.telemetryReporter, path => new Promise<boolean>(resolve => setTimeout(() => resolve(host.handles(path)), 750)), context.workspaceState));
|
||||
}, () => {
|
||||
// Nothing to do here. The client did show a message;
|
||||
});
|
||||
return clientHost;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function registerCommands(
|
||||
commandManager: CommandManager,
|
||||
lazyClientHost: () => TypeScriptServiceClientHost
|
||||
lazyClientHost: Lazy<TypeScriptServiceClientHost>
|
||||
) {
|
||||
commandManager.register(new commands.ReloadTypeScriptProjectsCommand(lazyClientHost));
|
||||
commandManager.register(new commands.ReloadJavaScriptProjectsCommand(lazyClientHost));
|
||||
|
||||
@@ -15,6 +15,7 @@ import TsConfigProvider, { TSConfig } from '../utils/tsconfigProvider';
|
||||
import { isImplicitProjectConfigFile } from '../utils/tsconfig';
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
import { Lazy } from '../utils/lazy';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
type AutoDetect = 'on' | 'off' | 'build' | 'watch';
|
||||
@@ -42,7 +43,7 @@ class TscTaskProvider implements vscode.TaskProvider {
|
||||
private readonly disposables: vscode.Disposable[] = [];
|
||||
|
||||
public constructor(
|
||||
private readonly lazyClient: () => ITypeScriptServiceClient
|
||||
private readonly client: Lazy<ITypeScriptServiceClient>
|
||||
) {
|
||||
this.tsconfigProvider = new TsConfigProvider();
|
||||
|
||||
@@ -104,7 +105,7 @@ class TscTaskProvider implements vscode.TaskProvider {
|
||||
}
|
||||
|
||||
try {
|
||||
const res: Proto.ProjectInfoResponse = await this.lazyClient().execute(
|
||||
const res: Proto.ProjectInfoResponse = await this.client.value.execute(
|
||||
'projectInfo',
|
||||
{ file, needFileNameList: false },
|
||||
token);
|
||||
@@ -166,7 +167,7 @@ class TscTaskProvider implements vscode.TaskProvider {
|
||||
if (editor) {
|
||||
const document = editor.document;
|
||||
if (document && (document.languageId === 'typescript' || document.languageId === 'typescriptreact')) {
|
||||
return this.lazyClient().normalizePath(document.uri);
|
||||
return this.client.value.normalizePath(document.uri);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -242,7 +243,7 @@ export default class TypeScriptTaskProviderManager {
|
||||
private readonly disposables: vscode.Disposable[] = [];
|
||||
|
||||
constructor(
|
||||
private readonly lazyClient: () => ITypeScriptServiceClient
|
||||
private readonly client: Lazy<ITypeScriptServiceClient>
|
||||
) {
|
||||
vscode.workspace.onDidChangeConfiguration(this.onConfigurationChanged, this, this.disposables);
|
||||
this.onConfigurationChanged();
|
||||
@@ -262,7 +263,7 @@ export default class TypeScriptTaskProviderManager {
|
||||
this.taskProviderSub.dispose();
|
||||
this.taskProviderSub = undefined;
|
||||
} else if (!this.taskProviderSub && autoDetect !== 'off') {
|
||||
this.taskProviderSub = vscode.workspace.registerTaskProvider('typescript', new TscTaskProvider(this.lazyClient));
|
||||
this.taskProviderSub = vscode.workspace.registerTaskProvider('typescript', new TscTaskProvider(this.client));
|
||||
}
|
||||
}
|
||||
}
|
||||
39
extensions/typescript/src/utils/lazy.ts
Normal file
39
extensions/typescript/src/utils/lazy.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export interface Lazy<T> {
|
||||
value: T;
|
||||
hasValue: boolean;
|
||||
map<R>(f: (x: T) => R): Lazy<R>;
|
||||
}
|
||||
|
||||
class LazyValue<T> implements Lazy<T> {
|
||||
private _hasValue: boolean = false;
|
||||
private _value: T;
|
||||
|
||||
constructor(
|
||||
private readonly _getValue: () => T
|
||||
) { }
|
||||
|
||||
get value(): T {
|
||||
if (!this._hasValue) {
|
||||
this._hasValue = true;
|
||||
this._value = this._getValue();
|
||||
}
|
||||
return this._value;
|
||||
}
|
||||
|
||||
get hasValue(): boolean {
|
||||
return this._hasValue;
|
||||
}
|
||||
|
||||
public map<R>(f: (x: T) => R): Lazy<R> {
|
||||
return new LazyValue(() => f(this.value));
|
||||
}
|
||||
}
|
||||
|
||||
export function lazy<T>(getValue: () => T): Lazy<T> {
|
||||
return new LazyValue<T>(getValue);
|
||||
}
|
||||
Reference in New Issue
Block a user