diff --git a/src/annotations/fileAnnotationController.ts b/src/annotations/fileAnnotationController.ts index 52cda9a..67b0525 100644 --- a/src/annotations/fileAnnotationController.ts +++ b/src/annotations/fileAnnotationController.ts @@ -27,7 +27,9 @@ import { Colors, ContextKeys, isTextEditor, setContext } from '../constants'; import { Container } from '../container'; import { KeyboardScope } from '../keyboard'; import { Logger } from '../logger'; -import { Functions, Iterables } from '../system'; +import { once } from '../system/event'; +import { debounce } from '../system/function'; +import { find } from '../system/iterable'; import { basename } from '../system/path'; import { DocumentBlameStateChangeEvent, @@ -80,7 +82,7 @@ export class FileAnnotationController implements Disposable { constructor(private readonly container: Container) { this._disposable = Disposable.from( - container.onReady(this.onReady, this), + once(container.onReady)(this.onReady, this), configuration.onDidChange(this.onConfigurationChanged, this), ); @@ -293,7 +295,7 @@ export class FileAnnotationController implements Disposable { const provider = this.getProvider(e.textEditor); if (provider == null) { // If we don't find an exact match, do a fuzzy match (since we can't properly track editors) - const fuzzyProvider = Iterables.find( + const fuzzyProvider = find( this._annotationProviders.values(), p => p.editor.document === e.textEditor.document, ); @@ -566,9 +568,9 @@ export class FileAnnotationController implements Disposable { Logger.log('Add listener registrations for annotations'); this._annotationsDisposable = Disposable.from( - window.onDidChangeActiveTextEditor(Functions.debounce(this.onActiveTextEditorChanged, 50), this), + window.onDidChangeActiveTextEditor(debounce(this.onActiveTextEditorChanged, 50), this), window.onDidChangeTextEditorViewColumn(this.onTextEditorViewColumnChanged, this), - window.onDidChangeVisibleTextEditors(Functions.debounce(this.onVisibleTextEditorsChanged, 50), this), + window.onDidChangeVisibleTextEditors(debounce(this.onVisibleTextEditorsChanged, 50), this), workspace.onDidCloseTextDocument(this.onTextDocumentClosed, this), this.container.tracker.onDidChangeBlameState(this.onBlameStateChanged, this), this.container.tracker.onDidChangeDirtyState(this.onDirtyStateChanged, this), diff --git a/src/annotations/lineAnnotationController.ts b/src/annotations/lineAnnotationController.ts index 4dec000..41e79a5 100644 --- a/src/annotations/lineAnnotationController.ts +++ b/src/annotations/lineAnnotationController.ts @@ -17,7 +17,9 @@ import { CommitFormatter } from '../git/formatters'; import { GitBlameCommit, PullRequest } from '../git/models'; import { Authentication } from '../git/remotes/provider'; import { LogCorrelationContext, Logger } from '../logger'; -import { debug, Iterables, log } from '../system'; +import { debug, log } from '../system/decorators/log'; +import { once } from '../system/event'; +import { count, every, filterMap } from '../system/iterable'; import { PromiseCancelledError, PromiseCancelledErrorWithId, raceAll } from '../system/promise'; import { LinesChangeEvent, LineSelection } from '../trackers/gitLineTracker'; import { Annotations } from './annotations'; @@ -38,7 +40,7 @@ export class LineAnnotationController implements Disposable { constructor(private readonly container: Container) { this._disposable = Disposable.from( - container.onReady(this.onReady, this), + once(container.onReady)(this.onReady, this), configuration.onDidChange(this.onConfigurationChanged, this), container.fileAnnotations.onDidToggleAnnotations(this.onFileAnnotationsToggled, this), Authentication.onDidChange(() => void this.refresh(window.activeTextEditor)), @@ -175,7 +177,7 @@ export class LineAnnotationController implements Disposable { ref => this.container.git.getPullRequestForCommit(ref, provider), timeout, ); - if (prs.size === 0 || Iterables.every(prs.values(), pr => pr == null)) return undefined; + if (prs.size === 0 || every(prs.values(), pr => pr == null)) return undefined; return prs; } @@ -248,7 +250,7 @@ export class LineAnnotationController implements Disposable { } const commitLines = [ - ...Iterables.filterMap(selections, selection => { + ...filterMap(selections, selection => { const state = this.container.lineTracker.getState(selection.active); if (state?.commit == null) { Logger.debug(cc, `Line ${selection.active} returned no commit`); @@ -342,10 +344,10 @@ export class LineAnnotationController implements Disposable { cc: LogCorrelationContext | undefined, ) { // If there are any PRs that timed out, refresh the annotation(s) once they complete - const count = Iterables.count(prs.values(), pr => pr instanceof PromiseCancelledError); - if (cancellationToken.isCancellationRequested || count === 0) return; + const prCount = count(prs.values(), pr => pr instanceof PromiseCancelledError); + if (cancellationToken.isCancellationRequested || prCount === 0) return; - Logger.debug(cc, `${GlyphChars.Dot} ${count} pull request queries took too long (over ${timeout} ms)`); + Logger.debug(cc, `${GlyphChars.Dot} ${prCount} pull request queries took too long (over ${timeout} ms)`); const resolved = new Map(); for (const [key, value] of prs) { @@ -354,7 +356,7 @@ export class LineAnnotationController implements Disposable { if (cancellationToken.isCancellationRequested || editor !== this._editor) return; - Logger.debug(cc, `${GlyphChars.Dot} ${count} pull request queries completed; refreshing...`); + Logger.debug(cc, `${GlyphChars.Dot} ${prCount} pull request queries completed; refreshing...`); void this.refresh(editor, { prs: resolved }); } diff --git a/src/codelens/codeLensController.ts b/src/codelens/codeLensController.ts index 104bd4d..9c34b87 100644 --- a/src/codelens/codeLensController.ts +++ b/src/codelens/codeLensController.ts @@ -3,6 +3,7 @@ import { configuration } from '../configuration'; import { ContextKeys, setContext } from '../constants'; import { Container } from '../container'; import { Logger } from '../logger'; +import { once } from '../system/event'; import { DocumentBlameStateChangeEvent, DocumentDirtyIdleTriggerEvent, @@ -18,7 +19,7 @@ export class GitCodeLensController implements Disposable { constructor(private readonly container: Container) { this._disposable = Disposable.from( - container.onReady(this.onReady, this), + once(container.onReady)(this.onReady, this), configuration.onDidChange(this.onConfigurationChanged, this), ); } diff --git a/src/container.ts b/src/container.ts index 5d896f6..2e00d6d 100644 --- a/src/container.ts +++ b/src/container.ts @@ -20,7 +20,8 @@ import { LineHoverController } from './hovers/lineHoverController'; import { Keyboard } from './keyboard'; import { Logger } from './logger'; import { StatusBarController } from './statusbar/statusBarController'; -import { log, memoize } from './system'; +import { log } from './system/decorators/log'; +import { memoize } from './system/decorators/memoize'; import { GitTerminalLinkProvider } from './terminal/linkProvider'; import { GitDocumentTracker } from './trackers/gitDocumentTracker'; import { GitLineTracker } from './trackers/gitLineTracker'; diff --git a/src/extension.ts b/src/extension.ts index cebc423..eeb226e 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -11,7 +11,9 @@ import { GitBranch, GitCommit } from './git/models'; import { Logger, LogLevel } from './logger'; import { Messages } from './messages'; import { registerPartnerActionRunners } from './partners'; -import { Stopwatch, Versions } from './system'; +import { once } from './system/event'; +import { Stopwatch } from './system/stopwatch'; +import { compare } from './system/version'; import { ViewNode } from './views/nodes'; export function activate(context: ExtensionContext): Promise | undefined { @@ -68,7 +70,7 @@ export function activate(context: ExtensionContext): Promise { + once(container.onReady)(() => { context.subscriptions.push(...registerCommands(container)); registerBuiltInActionRunners(container); registerPartnerActionRunners(context); @@ -106,7 +108,7 @@ export function activate(context: ExtensionContext): Promise(event: Event): Event { + return (listener: (e: T) => unknown, thisArgs?: unknown, disposables?: Disposable[]) => { + const result = event( + e => { + result.dispose(); + return listener.call(thisArgs, e); + }, + null, + disposables, + ); + + return result; + }; +} diff --git a/src/trackers/documentTracker.ts b/src/trackers/documentTracker.ts index bca45ac..96a3d9f 100644 --- a/src/trackers/documentTracker.ts +++ b/src/trackers/documentTracker.ts @@ -21,7 +21,9 @@ import { Container } from '../container'; import { RepositoriesChangeEvent } from '../git/gitProviderService'; import { GitUri } from '../git/gitUri'; import { RepositoryChange, RepositoryChangeComparisonMode, RepositoryChangeEvent } from '../git/models'; -import { Functions, Iterables } from '../system'; +import { once } from '../system/event'; +import { debounce, Deferrable } from '../system/function'; +import { filter, map } from '../system/iterable'; import { DocumentBlameStateChangeEvent, TrackedDocument } from './trackedDocument'; export * from './trackedDocument'; @@ -71,11 +73,11 @@ export class DocumentTracker implements Disposable { constructor(protected readonly container: Container) { this._disposable = Disposable.from( - container.onReady(this.onReady, this), + once(container.onReady)(this.onReady, this), configuration.onDidChange(this.onConfigurationChanged, this), window.onDidChangeActiveTextEditor(this.onActiveTextEditorChanged, this), - // window.onDidChangeVisibleTextEditors(Functions.debounce(this.onVisibleEditorsChanged, 5000), this), - workspace.onDidChangeTextDocument(Functions.debounce(this.onTextDocumentChanged, 50), this), + // window.onDidChangeVisibleTextEditors(debounce(this.onVisibleEditorsChanged, 5000), this), + workspace.onDidChangeTextDocument(debounce(this.onTextDocumentChanged, 50), this), workspace.onDidCloseTextDocument(this.onTextDocumentClosed, this), workspace.onDidSaveTextDocument(this.onTextDocumentSaved, this), this.container.git.onDidChangeRepositories(this.onRepositoriesChanged, this), @@ -348,12 +350,8 @@ export class DocumentTracker implements Disposable { return doc; } - private _dirtyIdleTriggeredDebounced: - | Functions.Deferrable<(e: DocumentDirtyIdleTriggerEvent) => void> - | undefined; - private _dirtyStateChangedDebounced: - | Functions.Deferrable<(e: DocumentDirtyStateChangeEvent) => void> - | undefined; + private _dirtyIdleTriggeredDebounced: Deferrable<(e: DocumentDirtyIdleTriggerEvent) => void> | undefined; + private _dirtyStateChangedDebounced: Deferrable<(e: DocumentDirtyStateChangeEvent) => void> | undefined; private fireDocumentDirtyStateChanged(e: DocumentDirtyStateChangeEvent) { if (e.dirty) { queueMicrotask(() => { @@ -365,7 +363,7 @@ export class DocumentTracker implements Disposable { if (this._dirtyIdleTriggerDelay > 0) { if (this._dirtyIdleTriggeredDebounced == null) { - this._dirtyIdleTriggeredDebounced = Functions.debounce( + this._dirtyIdleTriggeredDebounced = debounce( (e: DocumentDirtyIdleTriggerEvent) => { if (this._dirtyIdleTriggeredDebounced?.pending!()) return; @@ -384,7 +382,7 @@ export class DocumentTracker implements Disposable { } if (this._dirtyStateChangedDebounced == null) { - this._dirtyStateChangedDebounced = Functions.debounce((e: DocumentDirtyStateChangeEvent) => { + this._dirtyStateChangedDebounced = debounce((e: DocumentDirtyStateChangeEvent) => { if (window.activeTextEditor !== e.editor) return; this._onDidChangeDirtyState.fire(e); @@ -396,8 +394,8 @@ export class DocumentTracker implements Disposable { private reset(reason: 'config' | 'repository', changedRepoPaths?: Set, removedRepoPaths?: Set) { void Promise.allSettled( - Iterables.map( - Iterables.filter(this._documentMap, ([key]) => typeof key === 'string'), + map( + filter(this._documentMap, ([key]) => typeof key === 'string'), async ([, promise]) => { const doc = await promise; if (removedRepoPaths?.has(doc.uri.repoPath!)) { diff --git a/src/views/viewBase.ts b/src/views/viewBase.ts index 29f3058..f266280 100644 --- a/src/views/viewBase.ts +++ b/src/views/viewBase.ts @@ -34,6 +34,7 @@ import { import { Container } from '../container'; import { Logger } from '../logger'; import { debug, log } from '../system/decorators/log'; +import { once } from '../system/event'; import { debounce } from '../system/function'; import { cancellable, isPromise } from '../system/promise'; import { BranchesView } from './branchesView'; @@ -103,7 +104,7 @@ export abstract class ViewBase< private readonly _lastKnownLimits = new Map(); constructor(public readonly id: string, public readonly name: string, public readonly container: Container) { - this.disposables.push(container.onReady(this.onReady, this)); + this.disposables.push(once(container.onReady)(this.onReady, this)); if (Logger.isDebugging || this.container.config.debug) { function addDebuggingInfo(item: TreeItem, node: ViewNode, parent: ViewNode | undefined) {