Browse Source

Adds gating via @gate to many node methods

main
Eric Amodio 6 years ago
parent
commit
aceab8179d
11 changed files with 79 additions and 19 deletions
  1. +37
    -5
      src/system/decorators.ts
  2. +4
    -0
      src/system/function.ts
  3. +3
    -1
      src/views/nodes/fileHistoryTrackerNode.ts
  4. +3
    -1
      src/views/nodes/lineHistoryTrackerNode.ts
  5. +5
    -1
      src/views/nodes/repositoriesNode.ts
  6. +8
    -3
      src/views/nodes/repositoryNode.ts
  7. +1
    -1
      src/views/nodes/resultsCommitsNode.ts
  8. +1
    -1
      src/views/nodes/resultsFilesNode.ts
  9. +8
    -2
      src/views/nodes/resultsNode.ts
  10. +6
    -1
      src/views/nodes/viewNode.ts
  11. +3
    -3
      src/views/viewBase.ts

+ 37
- 5
src/system/decorators.ts View File

@ -1,5 +1,6 @@
'use strict';
import { Logger, LogLevel } from '../logger';
import { Functions } from './function';
import { Strings } from './string';
function decorate(decorator: (fn: Function, key: string) => Function): Function {
@ -177,11 +178,7 @@ export function log(
const start = options.timed ? process.hrtime() : undefined;
const result = fn.apply(this, args);
if (
result != null &&
(typeof result === 'object' || typeof result === 'function') &&
typeof result.then === 'function'
) {
if (result != null && Functions.isPromise(result)) {
const promise = result.then((r: any) => {
const timing =
start !== undefined ? ` \u2022 ${Strings.getDurationMilliseconds(start)} ms` : '';
@ -224,6 +221,41 @@ export function log(
};
}
export function gate() {
return (target: any, key: string, descriptor: PropertyDescriptor) => {
if (!(typeof descriptor.value === 'function')) throw new Error('not supported');
const gateKey = `$gate$${key}`;
const fn = descriptor.value;
descriptor.value = function(this: any, ...args: any[]) {
if (!this.hasOwnProperty(gateKey)) {
Object.defineProperty(this, gateKey, {
configurable: false,
enumerable: false,
writable: true,
value: undefined
});
}
let promise = this[gateKey];
if (promise === undefined) {
const result = fn.apply(this, args);
if (result == null || !Functions.isPromise(result)) {
return result;
}
this[gateKey] = promise = result.then((r: any) => {
this[gateKey] = undefined;
return r;
});
}
return promise;
};
};
}
function _memoize(fn: Function, key: string): Function {
const memoizeKey = `$memoize$${key}`;

+ 4
- 0
src/system/function.ts View File

@ -57,6 +57,10 @@ export namespace Functions {
return tracked;
}
export function isPromise(o: any) {
return (typeof o === 'object' || typeof o === 'function') && typeof o.then === 'function';
}
export function once<T extends Function>(fn: T): T {
return _once(fn);
}

+ 3
- 1
src/views/nodes/fileHistoryTrackerNode.ts View File

@ -4,7 +4,7 @@ import { Disposable, TextEditor, TreeItem, TreeItemCollapsibleState, Uri, window
import { UriComparer } from '../../comparers';
import { Container } from '../../container';
import { GitUri } from '../../git/gitService';
import { debug, Functions, log } from '../../system';
import { debug, Functions, gate, log } from '../../system';
import { FileHistoryView } from '../fileHistoryView';
import { MessageNode } from './common';
import { FileHistoryNode } from './fileHistoryNode';
@ -52,6 +52,8 @@ export class FileHistoryTrackerNode extends SubscribeableViewNode
return item;
}
@gate()
@debug()
async refresh() {
const editor = window.activeTextEditor;
if (editor == null || !Container.git.isTrackable(editor.document.uri)) {

+ 3
- 1
src/views/nodes/lineHistoryTrackerNode.ts View File

@ -3,7 +3,7 @@ import { Disposable, Selection, TreeItem, TreeItemCollapsibleState, window } fro
import { UriComparer } from '../../comparers';
import { Container } from '../../container';
import { GitUri } from '../../git/gitService';
import { debug, Functions, log } from '../../system';
import { debug, Functions, gate, log } from '../../system';
import { LinesChangeEvent } from '../../trackers/gitLineTracker';
import { LineHistoryView } from '../lineHistoryView';
import { MessageNode } from './common';
@ -53,6 +53,8 @@ export class LineHistoryTrackerNode extends SubscribeableViewNode
return item;
}
@gate()
@debug()
async refresh() {
const editor = window.activeTextEditor;
if (editor == null || !Container.git.isTrackable(editor.document.uri)) {

+ 5
- 1
src/views/nodes/repositoriesNode.ts View File

@ -3,7 +3,7 @@ import { Disposable, ProgressLocation, TextEditor, TreeItem, TreeItemCollapsible
import { Container } from '../../container';
import { GitUri } from '../../git/gitService';
import { Logger } from '../../logger';
import { debug, Functions, log } from '../../system';
import { debug, Functions, gate, log } from '../../system';
import { RepositoriesView } from '../repositoriesView';
import { RefreshReason } from '../viewBase';
import { MessageNode } from './common';
@ -57,6 +57,7 @@ export class RepositoriesNode extends SubscribeableViewNode {
return item;
}
@gate()
@log()
async fetchAll() {
if (this._children === undefined || this._children.length === 0) return;
@ -86,6 +87,7 @@ export class RepositoriesNode extends SubscribeableViewNode {
);
}
@gate()
@log()
async pullAll() {
if (this._children === undefined || this._children.length === 0) return;
@ -115,6 +117,8 @@ export class RepositoriesNode extends SubscribeableViewNode {
);
}
@gate()
@debug()
async refresh(reason?: RefreshReason) {
if (this._children === undefined) return;

+ 8
- 3
src/views/nodes/repositoryNode.ts View File

@ -13,7 +13,7 @@ import {
RepositoryChangeEvent,
RepositoryFileSystemChangeEvent
} from '../../git/gitService';
import { Dates, debug, Functions, log, Strings } from '../../system';
import { Dates, debug, Functions, gate, log, Strings } from '../../system';
import { RepositoriesView } from '../repositoriesView';
import { BranchesNode } from './branchesNode';
import { BranchNode } from './branchNode';
@ -168,6 +168,7 @@ export class RepositoryNode extends SubscribeableViewNode {
return item;
}
@gate()
@log()
async fetch(progress: boolean = true) {
if (!progress) return this.fetchCore();
@ -189,6 +190,7 @@ export class RepositoryNode extends SubscribeableViewNode {
this.view.triggerNodeChange(this);
}
@gate()
@log()
async pull(progress: boolean = true) {
if (!progress) return this.pullCore();
@ -210,6 +212,7 @@ export class RepositoryNode extends SubscribeableViewNode {
this.view.triggerNodeChange(this);
}
@gate()
@log()
async push(progress: boolean = true) {
if (!progress) return this.pushCore();
@ -230,11 +233,13 @@ export class RepositoryNode extends SubscribeableViewNode {
this.view.triggerNodeChange(this);
}
refresh() {
@gate()
@debug()
async refresh() {
this._status = this.repo.getStatus();
this._children = undefined;
void this.ensureSubscription();
await this.ensureSubscription();
}
@debug()

+ 1
- 1
src/views/nodes/resultsCommitsNode.ts View File

@ -53,7 +53,7 @@ export class ResultsCommitsNode extends ViewNode implements PageableViewNode {
return item;
}
async refresh() {
refresh() {
this._commitsQueryResults = this._commitsQuery(this.maxCount);
}

+ 1
- 1
src/views/nodes/resultsFilesNode.ts View File

@ -63,7 +63,7 @@ export class ResultsFilesNode extends ViewNode {
return item;
}
async refresh() {
refresh() {
this._filesQueryResults = this.getFilesQueryResultsCore();
}

+ 8
- 2
src/views/nodes/resultsNode.ts View File

@ -3,7 +3,7 @@ import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { ShowCommitSearchCommandArgs } from '../../commands';
import { GlyphChars } from '../../constants';
import { GitRepoSearchBy } from '../../git/gitService';
import { Strings } from '../../system';
import { debug, Functions, gate, log, Strings } from '../../system';
import { ResultsView } from '../resultsView';
import { CommandMessageNode, MessageNode } from './common';
import { ResourceType, unknownGitUri, ViewNode } from './viewNode';
@ -114,6 +114,7 @@ export class ResultsNode extends ViewNode {
this.view.triggerNodeChange();
}
@log()
clear() {
if (this._children.length === 0) return;
@ -121,6 +122,9 @@ export class ResultsNode extends ViewNode {
this.view.triggerNodeChange();
}
@log({
args: { 0: (n: ViewNode) => n.toString() }
})
dismiss(node: ViewNode) {
if (this._children.length === 0) return;
@ -131,9 +135,11 @@ export class ResultsNode extends ViewNode {
this.view.triggerNodeChange();
}
@gate()
@debug()
async refresh() {
if (this._children.length === 0) return;
this._children.forEach(c => c.refresh());
await Promise.all(this._children.map(c => c.refresh()).filter(Functions.isPromise) as Promise<any>[]);
}
}

+ 6
- 1
src/views/nodes/viewNode.ts View File

@ -1,7 +1,7 @@
'use strict';
import { Command, Disposable, Event, TreeItem, TreeItemCollapsibleState, TreeViewVisibilityChangeEvent } from 'vscode';
import { GitUri } from '../../git/gitService';
import { debug, logName } from '../../system';
import { debug, gate, logName } from '../../system';
import { RefreshReason, TreeViewNodeStateChangeEvent, View } from '../viewBase';
export enum ResourceType {
@ -65,6 +65,10 @@ export abstract class ViewNode {
this._uri = uri;
}
toString() {
return `${this.constructor.name}${this.id != null ? `(${this.id})` : ''}`;
}
protected _uri: GitUri;
get uri() {
return this._uri;
@ -82,6 +86,7 @@ export abstract class ViewNode {
return undefined;
}
@gate()
@debug()
refresh(reason?: RefreshReason): void | boolean | Promise<void> | Promise<boolean> {}
}

+ 3
- 3
src/views/viewBase.ts View File

@ -148,7 +148,7 @@ export abstract class ViewBase implements TreeDataProvid
}
@debug({
args: { 0: (n: ViewNode) => `${n.constructor.name}${n.id != null ? `(${n.id})` : ''}` }
args: { 0: (n: ViewNode) => n.toString() }
})
async refreshNode(node: ViewNode, args?: RefreshNodeCommandArgs) {
if (args !== undefined) {
@ -169,7 +169,7 @@ export abstract class ViewBase implements TreeDataProvid
}
@log({
args: { 0: (n: ViewNode) => `${n.constructor.name}${n.id != null ? `(${n.id})` : ''}` }
args: { 0: (n: ViewNode) => n.toString() }
})
async reveal(
node: ViewNode,
@ -198,7 +198,7 @@ export abstract class ViewBase implements TreeDataProvid
}
@debug({
args: { 0: (n?: ViewNode) => (n != null ? `${n.constructor.name}${n.id != null ? `(${n.id})` : ''}` : '') }
args: { 0: (n: ViewNode) => (n != null ? n.toString() : '') }
})
triggerNodeChange(node?: ViewNode) {
// Since the root node won't actually refresh, force everything

Loading…
Cancel
Save