提交 537deb52 编写于 作者: P Phil Price

Change document tracker to be opted out of per callee origin.

上级 aba193c3
...@@ -9,11 +9,12 @@ import { loadMessageBundle } from 'vscode-nls'; ...@@ -9,11 +9,12 @@ import { loadMessageBundle } from 'vscode-nls';
const localize = loadMessageBundle(); const localize = loadMessageBundle();
export default class MergeConflictCodeLensProvider implements vscode.CodeLensProvider, vscode.Disposable { export default class MergeConflictCodeLensProvider implements vscode.CodeLensProvider, vscode.Disposable {
private codeLensRegistrationHandle: vscode.Disposable | null; private codeLensRegistrationHandle: vscode.Disposable | null;
private config: interfaces.IExtensionConfiguration; private config: interfaces.IExtensionConfiguration;
private tracker: interfaces.IDocumentMergeConflictTracker;
constructor(private context: vscode.ExtensionContext, private tracker: interfaces.IDocumentMergeConflictTracker) { constructor(private context: vscode.ExtensionContext, trackerService: interfaces.IDocumentMergeConflictTrackerService) {
this.tracker = trackerService.createTracker('codelens');
} }
begin(config: interfaces.IExtensionConfiguration) { begin(config: interfaces.IExtensionConfiguration) {
......
...@@ -29,8 +29,10 @@ enum NavigationDirection { ...@@ -29,8 +29,10 @@ enum NavigationDirection {
export default class CommandHandler implements vscode.Disposable { export default class CommandHandler implements vscode.Disposable {
private disposables: vscode.Disposable[] = []; private disposables: vscode.Disposable[] = [];
private tracker: interfaces.IDocumentMergeConflictTracker;
constructor(private context: vscode.ExtensionContext, private tracker: interfaces.IDocumentMergeConflictTracker) { constructor(private context: vscode.ExtensionContext, trackerService: interfaces.IDocumentMergeConflictTrackerService) {
this.tracker = trackerService.createTracker('commands');
} }
begin() { begin() {
......
...@@ -8,29 +8,70 @@ import { MergeConflictParser } from './mergeConflictParser'; ...@@ -8,29 +8,70 @@ import { MergeConflictParser } from './mergeConflictParser';
import * as interfaces from './interfaces'; import * as interfaces from './interfaces';
import { Delayer } from './delayer'; import { Delayer } from './delayer';
export default class DocumentMergeConflictTracker implements vscode.Disposable, interfaces.IDocumentMergeConflictTracker { class ScanTask {
public origins: Set<string> = new Set<string>();
public delayTask: Delayer<interfaces.IDocumentMergeConflict[]>;
private cache: Map<string, Delayer<interfaces.IDocumentMergeConflict[]>> = new Map(); constructor(delayTime: number, initialOrigin: string) {
private delayExpireTime: number = 150; this.origins.add(initialOrigin);
this.delayTask = new Delayer<interfaces.IDocumentMergeConflict[]>(delayTime);
}
public addOrigin(name: string): boolean {
if (this.origins.has(name)) {
return false;
}
return false;
}
public hasOrigin(name: string): boolean {
return this.origins.has(name);
}
}
class OriginDocumentMergeConflictTracker implements interfaces.IDocumentMergeConflictTracker {
constructor(private parent: DocumentMergeConflictTracker, private origin: string) {
}
getConflicts(document: vscode.TextDocument): PromiseLike<interfaces.IDocumentMergeConflict[]> { getConflicts(document: vscode.TextDocument): PromiseLike<interfaces.IDocumentMergeConflict[]> {
return this.parent.getConflicts(document, this.origin);
}
isPending(document: vscode.TextDocument): boolean {
return this.parent.isPending(document, this.origin);
}
forget(document: vscode.TextDocument) {
this.parent.forget(document);
}
}
export default class DocumentMergeConflictTracker implements vscode.Disposable, interfaces.IDocumentMergeConflictTrackerService {
private cache: Map<string, ScanTask> = new Map();
private delayExpireTime: number = 300;
getConflicts(document: vscode.TextDocument, origin: string): PromiseLike<interfaces.IDocumentMergeConflict[]> {
// Attempt from cache // Attempt from cache
let key = this.getCacheKey(document); let key = this.getCacheKey(document);
if (!key) { if (!key) {
// Document doesnt have a uri, can't cache it, so return // Document doesnt have a uri, can't cache it, so return
return Promise.resolve(this.getConflictsOrEmpty(document)); return Promise.resolve(this.getConflictsOrEmpty(document, [origin]));
} }
let cacheItem = this.cache.get(key); let cacheItem = this.cache.get(key);
if (!cacheItem) { if (!cacheItem) {
cacheItem = new Delayer<interfaces.IDocumentMergeConflict[]>(this.delayExpireTime); cacheItem = new ScanTask(this.delayExpireTime, origin);
this.cache.set(key, cacheItem); this.cache.set(key, cacheItem);
} }
else {
cacheItem.addOrigin(origin);
}
return cacheItem.trigger(() => { return cacheItem.delayTask.trigger(() => {
let conflicts = this.getConflictsOrEmpty(document); let conflicts = this.getConflictsOrEmpty(document, Array.from(cacheItem!.origins));
if (this.cache) { if (this.cache) {
this.cache.delete(key!); this.cache.delete(key!);
...@@ -40,6 +81,29 @@ export default class DocumentMergeConflictTracker implements vscode.Disposable, ...@@ -40,6 +81,29 @@ export default class DocumentMergeConflictTracker implements vscode.Disposable,
}); });
} }
isPending(document: vscode.TextDocument, origin: string): boolean {
if (!document) {
return false;
}
let key = this.getCacheKey(document);
if (!key) {
return false;
}
var task = this.cache.get(key);
if (!task) {
return false;
}
return task.hasOrigin(origin);
}
createTracker(origin: string): interfaces.IDocumentMergeConflictTracker {
return new OriginDocumentMergeConflictTracker(this, origin);
}
forget(document: vscode.TextDocument) { forget(document: vscode.TextDocument) {
let key = this.getCacheKey(document); let key = this.getCacheKey(document);
...@@ -52,12 +116,12 @@ export default class DocumentMergeConflictTracker implements vscode.Disposable, ...@@ -52,12 +116,12 @@ export default class DocumentMergeConflictTracker implements vscode.Disposable,
this.cache.clear(); this.cache.clear();
} }
private getConflictsOrEmpty(document: vscode.TextDocument): interfaces.IDocumentMergeConflict[] { private getConflictsOrEmpty(document: vscode.TextDocument, origins: string[]): interfaces.IDocumentMergeConflict[] {
let stepStart = process.hrtime(); let stepStart = process.hrtime();
const containsConflict = MergeConflictParser.containsConflict(document); const containsConflict = MergeConflictParser.containsConflict(document);
let stepEnd = process.hrtime(stepStart); let stepEnd = process.hrtime(stepStart);
console.info('%s -> Check document execution time: %dms', document.uri.toString(), stepEnd[1] / 1000000); console.info('[%s] %s -> Check document execution time: %dms', origins.join(', '), document.uri.toString(), stepEnd[1] / 1000000);
if (!containsConflict) { if (!containsConflict) {
return []; return [];
...@@ -67,7 +131,7 @@ export default class DocumentMergeConflictTracker implements vscode.Disposable, ...@@ -67,7 +131,7 @@ export default class DocumentMergeConflictTracker implements vscode.Disposable,
const conflicts = MergeConflictParser.scanDocument(document); const conflicts = MergeConflictParser.scanDocument(document);
stepEnd = process.hrtime(stepStart); stepEnd = process.hrtime(stepStart);
console.info('%s -> Find conflict regions execution time: %dms', document.uri.toString(), stepEnd[1] / 1000000); console.info('[%s] %s -> Find conflict regions execution time: %dms', origins.join(', '), document.uri.toString(), stepEnd[1] / 1000000);
return conflicts; return conflicts;
} }
...@@ -79,4 +143,5 @@ export default class DocumentMergeConflictTracker implements vscode.Disposable, ...@@ -79,4 +143,5 @@ export default class DocumentMergeConflictTracker implements vscode.Disposable,
return null; return null;
} }
} }
\ No newline at end of file
...@@ -37,5 +37,11 @@ export interface IDocumentMergeConflictDescriptor { ...@@ -37,5 +37,11 @@ export interface IDocumentMergeConflictDescriptor {
export interface IDocumentMergeConflictTracker { export interface IDocumentMergeConflictTracker {
getConflicts(document: vscode.TextDocument): PromiseLike<IDocumentMergeConflict[]>; getConflicts(document: vscode.TextDocument): PromiseLike<IDocumentMergeConflict[]>;
isPending(document: vscode.TextDocument): boolean;
forget(document: vscode.TextDocument);
}
export interface IDocumentMergeConflictTrackerService {
createTracker(origin: string): IDocumentMergeConflictTracker;
forget(document: vscode.TextDocument); forget(document: vscode.TextDocument);
} }
...@@ -17,8 +17,10 @@ export default class MergeDectorator implements vscode.Disposable { ...@@ -17,8 +17,10 @@ export default class MergeDectorator implements vscode.Disposable {
private currentColorRgb = `32,200,94`; private currentColorRgb = `32,200,94`;
private incomingColorRgb = `24,134,255`; private incomingColorRgb = `24,134,255`;
private config: interfaces.IExtensionConfiguration; private config: interfaces.IExtensionConfiguration;
private tracker: interfaces.IDocumentMergeConflictTracker;
constructor(private context: vscode.ExtensionContext, private tracker: interfaces.IDocumentMergeConflictTracker) { constructor(private context: vscode.ExtensionContext, trackerService: interfaces.IDocumentMergeConflictTrackerService) {
this.tracker = trackerService.createTracker('decorator');
} }
begin(config: interfaces.IExtensionConfiguration) { begin(config: interfaces.IExtensionConfiguration) {
...@@ -149,10 +151,14 @@ export default class MergeDectorator implements vscode.Disposable { ...@@ -149,10 +151,14 @@ export default class MergeDectorator implements vscode.Disposable {
return; return;
} }
// If we have a pending scan from the same origin, exit early.
if (this.tracker.isPending(editor.document)) {
return;
}
let conflicts = await this.tracker.getConflicts(editor.document); let conflicts = await this.tracker.getConflicts(editor.document);
if (conflicts.length === 0) { if (conflicts.length === 0) {
// TODO: Remove decorations
this.removeDecorations(editor); this.removeDecorations(editor);
return; return;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册