diff --git a/package.json b/package.json index c2d3eab..df70d5a 100644 --- a/package.json +++ b/package.json @@ -3295,7 +3295,7 @@ { "id": "gitlens.gitExplorer", "name": "GitLens", - "when": "gitlens:enabled && gitlens:gitExplorer && config.gitlens.gitExplorer.enabled" + "when": "gitlens:enabled && gitlens:gitExplorer" }, { "id": "gitlens.resultsExplorer", diff --git a/src/commands.ts b/src/commands.ts index 0d4806e..ca4dc41 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -49,8 +49,11 @@ export * from './commands/toggleFileRecentChanges'; export * from './commands/toggleLineBlame'; import * as Commands from './commands'; +import { CommandContext, setCommandContext } from './constants'; export function configureCommands(): void { + setCommandContext(CommandContext.KeyMap, Container.config.keymap); + Container.context.subscriptions.push(commands.registerTextEditorCommand('gitlens.computingFileAnnotations', () => { })); Container.context.subscriptions.push(new Commands.CloseUnchangedFilesCommand()); diff --git a/src/container.ts b/src/container.ts index aecfa71..321f677 100644 --- a/src/container.ts +++ b/src/container.ts @@ -1,12 +1,14 @@ 'use strict'; -import { ExtensionContext } from 'vscode'; +import { Disposable, ExtensionContext, languages, workspace } from 'vscode'; import { AnnotationController } from './annotations/annotationController'; import { CodeLensController } from './codeLensController'; import { configuration, IConfig } from './configuration'; import { CurrentLineController } from './currentLineController'; import { DocumentTracker, GitDocumentState } from './trackers/documentTracker'; import { ExplorerCommands } from './views/explorerCommands'; +import { GitContentProvider } from './gitContentProvider'; import { GitExplorer } from './views/gitExplorer'; +import { GitRevisionCodeLensProvider } from './gitRevisionCodeLensProvider'; import { GitService } from './gitService'; import { Keyboard } from './keyboard'; import { ResultsExplorer } from './views/resultsExplorer'; @@ -14,33 +16,45 @@ import { ResultsExplorer } from './views/resultsExplorer'; export class Container { static initialize(context: ExtensionContext, config: IConfig) { - Container._context = context; - Container._config = config; + this._context = context; + this._config = config; - context.subscriptions.push(Container._tracker = new DocumentTracker()); - context.subscriptions.push(Container._git = new GitService()); + context.subscriptions.push(this._tracker = new DocumentTracker()); + context.subscriptions.push(this._git = new GitService()); // Since there is a chicken/egg problem with the DocumentTracker and the GitService, initialize the tracker once the GitService is loaded - Container._tracker.initialize(); + this._tracker.initialize(); - context.subscriptions.push(Container._annotationController = new AnnotationController()); - context.subscriptions.push(Container._currentLineController = new CurrentLineController()); - context.subscriptions.push(Container._codeLensController = new CodeLensController()); - context.subscriptions.push(Container._explorerCommands = new ExplorerCommands()); - context.subscriptions.push(Container._keyboard = new Keyboard()); + context.subscriptions.push(this._annotationController = new AnnotationController()); + context.subscriptions.push(this._currentLineController = new CurrentLineController()); + context.subscriptions.push(this._codeLensController = new CodeLensController()); + context.subscriptions.push(this._keyboard = new Keyboard()); - Container._gitExplorer = new GitExplorer(); - Container._resultsExplorer = new ResultsExplorer(); + if (config.gitExplorer.enabled) { + context.subscriptions.push(this._gitExplorer = new GitExplorer()); + } + else { + let disposable: Disposable; + disposable = configuration.onDidChange(e => { + if (configuration.changed(e, configuration.name('gitExplorer')('enabled').value)) { + disposable.dispose(); + context.subscriptions.push(this._gitExplorer = new GitExplorer()); + } + }); + } + + context.subscriptions.push(workspace.registerTextDocumentContentProvider(GitContentProvider.scheme, new GitContentProvider())); + context.subscriptions.push(languages.registerCodeLensProvider(GitRevisionCodeLensProvider.selector, new GitRevisionCodeLensProvider())); } private static _annotationController: AnnotationController; static get annotations() { - return Container._annotationController; + return this._annotationController; } private static _codeLensController: CodeLensController; static get codeLens() { - return Container._codeLensController; + return this._codeLensController; } private static _config: IConfig | undefined; @@ -53,42 +67,49 @@ export class Container { private static _context: ExtensionContext; static get context() { - return Container._context; + return this._context; } - private static _explorerCommands: ExplorerCommands; + private static _explorerCommands: ExplorerCommands | undefined; static get explorerCommands() { - return Container._explorerCommands; + if (this._explorerCommands === undefined) { + this._context.subscriptions.push(this._explorerCommands = new ExplorerCommands()); + } + return this._explorerCommands; } private static _git: GitService; static get git() { - return Container._git; + return this._git; } - private static _gitExplorer: GitExplorer; - static get gitExplorer() { - return Container._gitExplorer; + private static _gitExplorer: GitExplorer | undefined; + static get gitExplorer(): GitExplorer { + return this._gitExplorer!; } private static _keyboard: Keyboard; static get keyboard() { - return Container._keyboard; + return this._keyboard; } private static _currentLineController: CurrentLineController; static get lineAnnotations() { - return Container._currentLineController; + return this._currentLineController; } - private static _resultsExplorer: ResultsExplorer; + private static _resultsExplorer: ResultsExplorer | undefined; static get resultsExplorer() { - return Container._resultsExplorer; + if (this._resultsExplorer === undefined) { + this._context.subscriptions.push(this._resultsExplorer = new ResultsExplorer()); + } + + return this._resultsExplorer; } private static _tracker: DocumentTracker; static get tracker() { - return Container._tracker; + return this._tracker; } static resetConfig() { diff --git a/src/extension.ts b/src/extension.ts index 9ea87c5..520e9a7 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,12 +1,10 @@ 'use strict'; import { Objects, Versions } from './system'; -import { ConfigurationTarget, ExtensionContext, extensions, languages, window, workspace } from 'vscode'; +import { ConfigurationTarget, ExtensionContext, extensions, window, workspace } from 'vscode'; import { configuration, Configuration, IConfig } from './configuration'; import { CommandContext, ExtensionKey, GlobalState, QualifiedExtensionId, setCommandContext } from './constants'; import { configureCommands } from './commands'; import { Container } from './container'; -import { GitContentProvider } from './gitContentProvider'; -import { GitRevisionCodeLensProvider } from './gitRevisionCodeLensProvider'; import { GitService } from './gitService'; import { Logger } from './logger'; import { Messages, SuppressedMessages } from './messages'; @@ -64,21 +62,11 @@ export async function activate(context: ExtensionContext) { Container.initialize(context, cfg); - context.subscriptions.push(workspace.registerTextDocumentContentProvider(GitContentProvider.scheme, new GitContentProvider())); - context.subscriptions.push(languages.registerCodeLensProvider(GitRevisionCodeLensProvider.selector, new GitRevisionCodeLensProvider())); - - context.subscriptions.push(window.registerTreeDataProvider('gitlens.gitExplorer', Container.gitExplorer)); - context.subscriptions.push(window.registerTreeDataProvider('gitlens.resultsExplorer', Container.resultsExplorer)); - configureCommands(); // Constantly over my data cap so stop collecting initialized event // Telemetry.trackEvent('initialized', Objects.flatten(cfg, 'config', true)); - setCommandContext(CommandContext.KeyMap, configuration.get(configuration.name('keymap').value)); - // Slightly delay enabling the explorer to not stop the rest of GitLens from being usable - setTimeout(() => setCommandContext(CommandContext.GitExplorer, true), 1000); - const duration = process.hrtime(start); Logger.log(`GitLens(v${gitlensVersion}) activated in ${(duration[0] * 1000) + Math.floor(duration[1] / 1000000)} ms`); } diff --git a/src/views/gitExplorer.ts b/src/views/gitExplorer.ts index 1e4f6f2..fca909d 100644 --- a/src/views/gitExplorer.ts +++ b/src/views/gitExplorer.ts @@ -17,8 +17,9 @@ export interface OpenFileRevisionCommandArgs { showOptions?: TextDocumentShowOptions; } -export class GitExplorer implements TreeDataProvider { +export class GitExplorer extends Disposable implements TreeDataProvider { + private _disposable: Disposable | undefined; private _root?: ExplorerNode; private _view: GitExplorerView | undefined; @@ -33,14 +34,17 @@ export class GitExplorer implements TreeDataProvider { } constructor() { + super(() => this.dispose()); + + Container.explorerCommands; commands.registerCommand('gitlens.gitExplorer.refresh', this.refresh, this); commands.registerCommand('gitlens.gitExplorer.refreshNode', this.refreshNode, this); commands.registerCommand('gitlens.gitExplorer.setFilesLayoutToAuto', () => this.setFilesLayout(ExplorerFilesLayout.Auto), this); commands.registerCommand('gitlens.gitExplorer.setFilesLayoutToList', () => this.setFilesLayout(ExplorerFilesLayout.List), this); commands.registerCommand('gitlens.gitExplorer.setFilesLayoutToTree', () => this.setFilesLayout(ExplorerFilesLayout.Tree), this); - commands.registerCommand('gitlens.gitExplorer.setAutoRefreshToOn', () => this.setAutoRefresh(configuration.get(configuration.name('gitExplorer')('autoRefresh').value), true), this); - commands.registerCommand('gitlens.gitExplorer.setAutoRefreshToOff', () => this.setAutoRefresh(configuration.get(configuration.name('gitExplorer')('autoRefresh').value), false), this); + commands.registerCommand('gitlens.gitExplorer.setAutoRefreshToOn', () => this.setAutoRefresh(Container.config.gitExplorer.autoRefresh, true), this); + commands.registerCommand('gitlens.gitExplorer.setAutoRefreshToOff', () => this.setAutoRefresh(Container.config.gitExplorer.autoRefresh, false), this); commands.registerCommand('gitlens.gitExplorer.switchToHistoryView', () => this.switchTo(GitExplorerView.History), this); commands.registerCommand('gitlens.gitExplorer.switchToRepositoryView', () => this.switchTo(GitExplorerView.Repository), this); @@ -52,6 +56,10 @@ export class GitExplorer implements TreeDataProvider { this.onConfigurationChanged(configuration.initializingChangeEvent); } + dispose() { + this._disposable && this._disposable.dispose(); + } + private async onActiveEditorChanged(editor: TextEditor | undefined) { if (this._view !== GitExplorerView.History) return; @@ -68,11 +76,15 @@ export class GitExplorer implements TreeDataProvider { !configuration.changed(e, configuration.name('gitExplorer').value) && !configuration.changed(e, configuration.name('defaultGravatarsStyle').value)) return; + if (initializing || configuration.changed(e, configuration.name('gitExplorer')('enabled').value)) { + setCommandContext(CommandContext.GitExplorer, this.config.enabled); + } + if (initializing || configuration.changed(e, configuration.name('gitExplorer')('autoRefresh').value)) { - this.setAutoRefresh(configuration.get(configuration.name('gitExplorer')('autoRefresh').value)); + this.setAutoRefresh(Container.config.gitExplorer.autoRefresh); } - let view = configuration.get(configuration.name('gitExplorer')('view').value); + let view = this.config.view; if (view === GitExplorerView.Auto) { view = Container.context.workspaceState.get(WorkspaceState.GitExplorerView, GitExplorerView.Repository); } @@ -82,6 +94,8 @@ export class GitExplorer implements TreeDataProvider { setCommandContext(CommandContext.GitExplorerView, this._view); this.setRoot(await this.getRootNode(window.activeTextEditor)); + + this._disposable = window.registerTreeDataProvider('gitlens.gitExplorer', this); } else { this.reset(view); @@ -110,7 +124,7 @@ export class GitExplorer implements TreeDataProvider { } get autoRefresh() { - return configuration.get(configuration.name('gitExplorer')('autoRefresh').value) && + return this.config.autoRefresh && Container.context.workspaceState.get(WorkspaceState.GitExplorerAutoRefresh, true); } @@ -248,7 +262,7 @@ export class GitExplorer implements TreeDataProvider { setView(view: GitExplorerView) { if (this._view === view) return; - if (configuration.get(configuration.name('gitExplorer')('view').value) === GitExplorerView.Auto) { + if (Container.config.gitExplorer.view === GitExplorerView.Auto) { Container.context.workspaceState.update(WorkspaceState.GitExplorerView, view); } diff --git a/src/views/resultsExplorer.ts b/src/views/resultsExplorer.ts index 4445909..8a474cd 100644 --- a/src/views/resultsExplorer.ts +++ b/src/views/resultsExplorer.ts @@ -1,6 +1,6 @@ 'use strict'; import { Functions } from '../system'; -import { commands, ConfigurationChangeEvent, ConfigurationTarget, Event, EventEmitter, TreeDataProvider, TreeItem } from 'vscode'; +import { commands, ConfigurationChangeEvent, ConfigurationTarget, Disposable, Event, EventEmitter, TreeDataProvider, TreeItem, window } from 'vscode'; import { configuration, ExplorerFilesLayout, IExplorerConfig } from '../configuration'; import { CommandContext, setCommandContext, WorkspaceState } from '../constants'; import { Container } from '../container'; @@ -12,8 +12,9 @@ import { Messages } from '../messages'; export * from './explorerNodes'; -export class ResultsExplorer implements TreeDataProvider { +export class ResultsExplorer extends Disposable implements TreeDataProvider { + private _disposable: Disposable | undefined; private _roots: ExplorerNode[] = []; private _onDidChangeTreeData = new EventEmitter(); @@ -22,6 +23,9 @@ export class ResultsExplorer implements TreeDataProvider { } constructor() { + super(() => this.dispose()); + + Container.explorerCommands; commands.registerCommand('gitlens.resultsExplorer.refresh', this.refreshNodes, this); commands.registerCommand('gitlens.resultsExplorer.refreshNode', this.refreshNode, this); commands.registerCommand('gitlens.resultsExplorer.setFilesLayoutToAuto', () => this.setFilesLayout(ExplorerFilesLayout.Auto), this); @@ -41,6 +45,10 @@ export class ResultsExplorer implements TreeDataProvider { this.onConfigurationChanged(configuration.initializingChangeEvent); } + dispose() { + this._disposable && this._disposable.dispose(); + } + private async onConfigurationChanged(e: ConfigurationChangeEvent) { const initializing = configuration.initializing(e); @@ -51,6 +59,10 @@ export class ResultsExplorer implements TreeDataProvider { if (!initializing && this._roots.length !== 0) { this.refresh(RefreshReason.ConfigurationChanged); } + + if (initializing) { + this._disposable = window.registerTreeDataProvider('gitlens.resultsExplorer', this); + } } get config(): IExplorerConfig {