提交 afacd2bd 编写于 作者: E Eric Amodio

Fixes #89509, #91464, #91628, #91619

上级 77dcee27
......@@ -9,7 +9,7 @@ import { URI } from 'vs/base/common/uri';
import { ILogService } from 'vs/platform/log/common/log';
import { MainContext, MainThreadTimelineShape, IExtHostContext, ExtHostTimelineShape, ExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, ITimelineService } from 'vs/workbench/contrib/timeline/common/timeline';
import { TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, ITimelineService, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
@extHostNamedCustomer(MainContext.MainThreadTimeline)
export class MainThreadTimeline implements MainThreadTimelineShape {
......@@ -39,7 +39,7 @@ export class MainThreadTimeline implements MainThreadTimelineShape {
this._timelineService.registerTimelineProvider({
...provider,
onDidChange: onDidChange.event,
provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: { cacheResults?: boolean }) {
provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: InternalTimelineOptions) {
return proxy.$getTimeline(provider.id, uri, options, token, internalOptions);
},
dispose() {
......
......@@ -49,7 +49,7 @@ import { SaveReason } from 'vs/workbench/common/editor';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor } from 'vs/workbench/contrib/timeline/common/timeline';
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
import { revive } from 'vs/base/common/marshalling';
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { Dto } from 'vs/base/common/types';
......@@ -1468,7 +1468,7 @@ export interface ExtHostTunnelServiceShape {
}
export interface ExtHostTimelineShape {
$getTimeline(source: string, uri: UriComponents, options: TimelineOptions, token: CancellationToken, internalOptions?: { cacheResults?: boolean }): Promise<Timeline | undefined>;
$getTimeline(source: string, uri: UriComponents, options: TimelineOptions, token: CancellationToken, internalOptions?: InternalTimelineOptions): Promise<Timeline | undefined>;
}
// --- proxy identifiers
......
......@@ -7,7 +7,7 @@ import * as vscode from 'vscode';
import { UriComponents, URI } from 'vs/base/common/uri';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ExtHostTimelineShape, MainThreadTimelineShape, IMainContext, MainContext } from 'vs/workbench/api/common/extHost.protocol';
import { Timeline, TimelineItem, TimelineOptions, TimelineProvider } from 'vs/workbench/contrib/timeline/common/timeline';
import { Timeline, TimelineItem, TimelineOptions, TimelineProvider, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
import { IDisposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { CancellationToken } from 'vs/base/common/cancellation';
import { CommandsConverter, ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
......@@ -16,21 +16,19 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export interface IExtHostTimeline extends ExtHostTimelineShape {
readonly _serviceBrand: undefined;
$getTimeline(id: string, uri: UriComponents, options: vscode.TimelineOptions, token: vscode.CancellationToken, internalOptions?: { cacheResults?: boolean }): Promise<Timeline | undefined>;
$getTimeline(id: string, uri: UriComponents, options: vscode.TimelineOptions, token: vscode.CancellationToken, internalOptions?: InternalTimelineOptions): Promise<Timeline | undefined>;
}
export const IExtHostTimeline = createDecorator<IExtHostTimeline>('IExtHostTimeline');
export class ExtHostTimeline implements IExtHostTimeline {
private static handlePool = 0;
_serviceBrand: undefined;
private _proxy: MainThreadTimelineShape;
private _providers = new Map<string, TimelineProvider>();
private _itemsBySourceByUriMap = new Map<string | undefined, Map<string, Map<string, vscode.TimelineItem>>>();
private _itemsBySourceAndUriMap = new Map<string, Map<string | undefined, Map<string, vscode.TimelineItem>>>();
constructor(
mainContext: IMainContext,
......@@ -42,7 +40,7 @@ export class ExtHostTimeline implements IExtHostTimeline {
processArgument: arg => {
if (arg && arg.$mid === 11) {
const uri = arg.uri === undefined ? undefined : URI.revive(arg.uri);
return this._itemsBySourceByUriMap.get(getUriKey(uri))?.get(arg.source)?.get(arg.handle);
return this._itemsBySourceAndUriMap.get(arg.source)?.get(getUriKey(uri))?.get(arg.handle);
}
return arg;
......@@ -50,7 +48,7 @@ export class ExtHostTimeline implements IExtHostTimeline {
});
}
async $getTimeline(id: string, uri: UriComponents, options: vscode.TimelineOptions, token: vscode.CancellationToken, internalOptions?: { cacheResults?: boolean }): Promise<Timeline | undefined> {
async $getTimeline(id: string, uri: UriComponents, options: vscode.TimelineOptions, token: vscode.CancellationToken, internalOptions?: InternalTimelineOptions): Promise<Timeline | undefined> {
const provider = this._providers.get(id);
return provider?.provideTimeline(URI.revive(uri), options, token, internalOptions);
}
......@@ -62,26 +60,21 @@ export class ExtHostTimeline implements IExtHostTimeline {
let disposable: IDisposable | undefined;
if (provider.onDidChange) {
disposable = provider.onDidChange(this.emitTimelineChangeEvent(provider.id), this);
disposable = provider.onDidChange(e => this._proxy.$emitTimelineChangeEvent({ ...e, id: provider.id }), this);
}
const itemsBySourceByUriMap = this._itemsBySourceByUriMap;
const itemsBySourceAndUriMap = this._itemsBySourceAndUriMap;
return this.registerTimelineProviderCore({
...provider,
scheme: scheme,
onDidChange: undefined,
async provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: { cacheResults?: boolean }) {
// For now, only allow the caching of a single Uri
if (internalOptions?.cacheResults) {
if (options.cursor === undefined) {
timelineDisposables.clear();
}
if (!itemsBySourceByUriMap.has(getUriKey(uri))) {
itemsBySourceByUriMap.clear();
}
} else {
async provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: InternalTimelineOptions) {
if (internalOptions?.resetCache) {
timelineDisposables.clear();
// For now, only allow the caching of a single Uri
// itemsBySourceAndUriMap.get(provider.id)?.get(getUriKey(uri))?.clear();
itemsBySourceAndUriMap.get(provider.id)?.clear();
}
const result = await provider.provideTimeline(uri, options, token);
......@@ -91,8 +84,9 @@ export class ExtHostTimeline implements IExtHostTimeline {
return undefined;
}
// TODO: Determine if we should cache dependent on who calls us (internal vs external)
const convertItem = convertTimelineItem(uri, internalOptions?.cacheResults ?? false);
// TODO: Should we bother converting all the data if we aren't caching? Meaning it is being requested by an extension?
const convertItem = convertTimelineItem(uri, internalOptions);
return {
...result,
source: provider.id,
......@@ -100,6 +94,10 @@ export class ExtHostTimeline implements IExtHostTimeline {
};
},
dispose() {
for (const sourceMap of itemsBySourceAndUriMap.values()) {
sourceMap.get(provider.id)?.clear();
}
disposable?.dispose();
timelineDisposables.dispose();
}
......@@ -107,29 +105,28 @@ export class ExtHostTimeline implements IExtHostTimeline {
}
private convertTimelineItem(source: string, commandConverter: CommandsConverter, disposables: DisposableStore) {
return (uri: URI, cacheResults: boolean) => {
let itemsMap: Map<string, vscode.TimelineItem> | undefined;
if (cacheResults) {
const uriKey = getUriKey(uri);
let sourceMap = this._itemsBySourceByUriMap.get(uriKey);
if (sourceMap === undefined) {
sourceMap = new Map();
this._itemsBySourceByUriMap.set(uriKey, sourceMap);
return (uri: URI, options?: InternalTimelineOptions) => {
let items: Map<string, vscode.TimelineItem> | undefined;
if (options?.cacheResults) {
let itemsByUri = this._itemsBySourceAndUriMap.get(source);
if (itemsByUri === undefined) {
itemsByUri = new Map();
this._itemsBySourceAndUriMap.set(source, itemsByUri);
}
itemsMap = sourceMap.get(source);
if (itemsMap === undefined) {
itemsMap = new Map();
sourceMap.set(source, itemsMap);
const uriKey = getUriKey(uri);
items = itemsByUri.get(uriKey);
if (items === undefined) {
items = new Map();
itemsByUri.set(uriKey, items);
}
}
return (item: vscode.TimelineItem): TimelineItem => {
const { iconPath, ...props } = item;
const handle = `${source}|${item.id ?? `${item.timestamp}-${ExtHostTimeline.handlePool++}`}`;
itemsMap?.set(handle, item);
const handle = `${source}|${item.id ?? item.timestamp}`;
items?.set(handle, item);
let icon;
let iconDark;
......@@ -161,22 +158,6 @@ export class ExtHostTimeline implements IExtHostTimeline {
};
}
private emitTimelineChangeEvent(id: string) {
return (e: vscode.TimelineChangeEvent) => {
// Clear caches
if (e?.uri === undefined) {
for (const sourceMap of this._itemsBySourceByUriMap.values()) {
sourceMap.get(id)?.clear();
}
}
else {
this._itemsBySourceByUriMap.get(getUriKey(e.uri))?.clear();
}
this._proxy.$emitTimelineChangeEvent({ ...e, id: id });
};
}
private registerTimelineProviderCore(provider: TimelineProvider): IDisposable {
// console.log(`ExtHostTimeline#registerTimelineProvider: id=${provider.id}`);
......@@ -193,7 +174,7 @@ export class ExtHostTimeline implements IExtHostTimeline {
this._providers.set(provider.id, provider);
return toDisposable(() => {
for (const sourceMap of this._itemsBySourceByUriMap.values()) {
for (const sourceMap of this._itemsBySourceAndUriMap.values()) {
sourceMap.get(provider.id)?.clear();
}
......
......@@ -7,9 +7,25 @@
position: relative;
}
.monaco-workbench .timeline-view.pane-header .description {
margin-left: 10px;
opacity: 0.6;
text-transform: none;
font-weight: normal;
}
.monaco-workbench .timeline-view.pane-header:not(.expanded) .description {
display: none;
}
.monaco-workbench .timeline-view.pane-header .description span.codicon {
font-size: 9px;
margin-left: 2px;
}
.monaco-workbench .timeline-tree-view .message.timeline-subtle {
padding: 10px 22px 0 22px;
opacity: 0.5;
padding: 10px 22px 0 22px;
position: absolute;
pointer-events: none;
z-index: 1;
......
......@@ -89,9 +89,10 @@ export class TimelinePane extends ViewPane {
static readonly ID = 'timeline';
static readonly TITLE = localize('timeline', 'Timeline');
private _container!: HTMLElement;
private _messageElement!: HTMLDivElement;
private _treeElement!: HTMLDivElement;
private _$container!: HTMLElement;
private _$message!: HTMLDivElement;
private _$titleDescription!: HTMLSpanElement;
private _$tree!: HTMLDivElement;
private _tree!: WorkbenchObjectTree<TreeElement, FuzzyScore>;
private _treeRenderer: TimelineTreeRenderer | undefined;
private _menus: TimelineMenus;
......@@ -100,7 +101,6 @@ export class TimelinePane extends ViewPane {
private _excludedSources: Set<string>;
private _cursorsByProvider: Map<string, TimelineCursors> = new Map();
private _items: { element: TreeElement }[] = [];
private _loadingMessageTimer: any | undefined;
private _pendingRequests = new Map<string, TimelineRequest>();
private _uri: URI | undefined;
......@@ -181,6 +181,17 @@ export class TimelinePane extends ViewPane {
this.loadTimeline(true);
}
private _titleDescription: string | undefined;
get titleDescription(): string | undefined {
return this._titleDescription;
}
set titleDescription(description: string | undefined) {
this._titleDescription = description;
this._$titleDescription.textContent = description ?? '';
}
private _message: string | undefined;
get message(): string | undefined {
return this._message;
......@@ -192,7 +203,7 @@ export class TimelinePane extends ViewPane {
}
private updateMessage(): void {
if (this._message) {
if (this._message !== undefined) {
this.showMessage(this._message);
} else {
this.hideMessage();
......@@ -200,35 +211,32 @@ export class TimelinePane extends ViewPane {
}
private showMessage(message: string): void {
DOM.removeClass(this._messageElement, 'hide');
DOM.removeClass(this._$message, 'hide');
this.resetMessageElement();
this._messageElement.textContent = message;
this._$message.textContent = message;
}
private hideMessage(): void {
this.resetMessageElement();
DOM.addClass(this._messageElement, 'hide');
DOM.addClass(this._$message, 'hide');
}
private resetMessageElement(): void {
DOM.clearNode(this._messageElement);
DOM.clearNode(this._$message);
}
private _pendingAnyResults: boolean = false;
private async loadTimeline(reset: boolean, sources?: string[], options: TimelineOptions = {}) {
const defaultPageSize = reset ? InitialPageSize : SubsequentPageSize;
// If we have no source, we are reseting all sources, so cancel everything in flight and reset caches
if (sources === undefined) {
if (reset) {
this._pendingAnyResults = this._pendingAnyResults || this._items.length !== 0;
this._items.length = 0;
this._cursorsByProvider.clear();
if (this._loadingMessageTimer) {
clearTimeout(this._loadingMessageTimer);
this._loadingMessageTimer = undefined;
}
for (const { tokenSource } of this._pendingRequests.values()) {
tokenSource.dispose(true);
}
......@@ -237,26 +245,23 @@ export class TimelinePane extends ViewPane {
}
// TODO[ECA]: Are these the right the list of schemes to exclude? Is there a better way?
if (this._uri && (this._uri.scheme === 'vscode-settings' || this._uri.scheme === 'webview-panel' || this._uri.scheme === 'walkThrough')) {
this.message = localize('timeline.editorCannotProvideTimeline', 'The active editor cannot provide timeline information.');
this._tree.setChildren(null, undefined);
if (this._uri?.scheme === 'vscode-settings' || this._uri?.scheme === 'webview-panel' || this._uri?.scheme === 'walkThrough') {
this._uri = undefined;
this._items.length = 0;
this.refresh();
return;
}
if (reset && this._uri !== undefined) {
this._loadingMessageTimer = setTimeout((uri: URI) => {
if (uri !== this._uri) {
return;
}
this._tree.setChildren(null, undefined);
this.message = localize('timeline.loading', 'Loading timeline for {0}...', basename(uri.fsPath));
}, 500, this._uri);
if (!this._pendingAnyResults && this._uri !== undefined) {
this.setLoadingUriMessage();
}
}
if (this._uri === undefined) {
this._items.length = 0;
this.refresh();
return;
}
......@@ -284,6 +289,8 @@ export class TimelinePane extends ViewPane {
}
}
let noRequests = true;
for (const source of filteredSources) {
let request = this._pendingRequests.get(source);
......@@ -303,13 +310,14 @@ export class TimelinePane extends ViewPane {
...options,
limit: options.limit === 0 ? undefined : options.limit ?? defaultPageSize
},
request?.tokenSource ?? new CancellationTokenSource(), { cacheResults: true }
request?.tokenSource ?? new CancellationTokenSource(), { cacheResults: true, resetCache: false }
)!;
if (request === undefined) {
continue;
}
noRequests = false;
this._pendingRequests.set(source, request);
if (!reusingToken) {
request.tokenSource.token.onCancellationRequested(() => this._pendingRequests.delete(source));
......@@ -323,19 +331,24 @@ export class TimelinePane extends ViewPane {
...options,
limit: options.limit === 0 ? undefined : (reset ? cursors?.endCursors?.after : undefined) ?? options.limit ?? defaultPageSize
},
new CancellationTokenSource(), { cacheResults: true }
new CancellationTokenSource(), { cacheResults: true, resetCache: true }
)!;
if (request === undefined) {
continue;
}
noRequests = false;
this._pendingRequests.set(source, request);
request.tokenSource.token.onCancellationRequested(() => this._pendingRequests.delete(source));
}
this.handleRequest(request);
}
if (noRequests) {
this.refresh();
}
}
private async handleRequest(request: TimelineRequest) {
......@@ -348,13 +361,20 @@ export class TimelinePane extends ViewPane {
}
if (
timeline === undefined ||
request.tokenSource.token.isCancellationRequested ||
request.uri !== this._uri
) {
return;
}
if (timeline === undefined) {
if (this._pendingRequests.size === 0) {
this.refresh();
}
return;
}
let items: TreeElement[];
const source = request.source;
......@@ -512,15 +532,19 @@ export class TimelinePane extends ViewPane {
}
private refresh() {
if (this._loadingMessageTimer) {
clearTimeout(this._loadingMessageTimer);
this._loadingMessageTimer = undefined;
}
this._pendingAnyResults = false;
if (this._items.length === 0) {
this.message = localize('timeline.noTimelineInfo', 'No timeline information was provided.');
} else {
this.message = undefined;
if (this._uri === undefined) {
this.titleDescription = undefined;
this.message = localize('timeline.editorCannotProvideTimeline', 'The active editor cannot provide timeline information.');
}
else {
this.titleDescription = basename(this._uri.fsPath);
if (this._items.length === 0) {
this.message = localize('timeline.noTimelineInfo', 'No timeline information was provided.');
} else {
this.message = undefined;
}
}
this._tree.setChildren(null, this._items);
......@@ -555,23 +579,30 @@ export class TimelinePane extends ViewPane {
this._tree.layout(height, width);
}
protected renderHeaderTitle(container: HTMLElement): void {
super.renderHeaderTitle(container, this.title);
DOM.addClass(container, 'timeline-view');
this._$titleDescription = DOM.append(container, DOM.$('span.description', undefined, this.titleDescription ?? ''));
}
protected renderBody(container: HTMLElement): void {
this._container = container;
this._$container = container;
DOM.addClasses(container, 'tree-explorer-viewlet-tree-view', 'timeline-tree-view');
this._messageElement = DOM.append(this._container, DOM.$('.message'));
DOM.addClass(this._messageElement, 'timeline-subtle');
this._$message = DOM.append(this._$container, DOM.$('.message'));
DOM.addClass(this._$message, 'timeline-subtle');
this.message = localize('timeline.editorCannotProvideTimeline', 'The active editor cannot provide timeline information.');
this._treeElement = document.createElement('div');
DOM.addClasses(this._treeElement, 'customview-tree', 'file-icon-themable-tree', 'hide-arrows');
this._$tree = document.createElement('div');
DOM.addClasses(this._$tree, 'customview-tree', 'file-icon-themable-tree', 'hide-arrows');
// DOM.addClass(this._treeElement, 'show-file-icons');
container.appendChild(this._treeElement);
container.appendChild(this._$tree);
this._treeRenderer = this.instantiationService.createInstance(TimelineTreeRenderer, this._menus);
this._tree = <WorkbenchObjectTree<TreeElement, FuzzyScore>>this.instantiationService.createInstance(WorkbenchObjectTree, 'TimelinePane',
this._treeElement, new TimelineListVirtualDelegate(), [this._treeRenderer], {
this._$tree, new TimelineListVirtualDelegate(), [this._treeRenderer], {
identityProvider: new TimelineIdentityProvider(),
keyboardNavigationLabelProvider: new TimelineKeyboardNavigationLabelProvider(),
overrideStyles: {
......@@ -583,9 +614,10 @@ export class TimelinePane extends ViewPane {
const customTreeNavigator = new TreeResourceNavigator(this._tree, { openOnFocus: false, openOnSelection: false });
this._register(customTreeNavigator);
this._register(this._tree.onContextMenu(e => this.onContextMenu(this._menus, e)));
this._register(this._tree.onDidChangeSelection(e => this.ensureValidItems()));
this._register(
customTreeNavigator.onDidOpenResource(e => {
if (!e.browserEvent) {
if (!e.browserEvent || !this.ensureValidItems()) {
return;
}
......@@ -612,6 +644,24 @@ export class TimelinePane extends ViewPane {
})
);
}
ensureValidItems() {
if (this._pendingAnyResults) {
this._tree.setChildren(null, undefined);
this.setLoadingUriMessage();
this._pendingAnyResults = false;
return false;
}
return true;
}
setLoadingUriMessage() {
const file = this._uri && basename(this._uri.fsPath);
this.titleDescription = file ?? '';
this.message = file ? localize('timeline.loading', 'Loading timeline for {0}...', file) : '';
}
private onContextMenu(menus: TimelineMenus, treeEvent: ITreeContextMenuEvent<TreeElement | null>): void {
const item = treeEvent.element;
......@@ -623,6 +673,10 @@ export class TimelinePane extends ViewPane {
event.preventDefault();
event.stopPropagation();
if (!this.ensureValidItems()) {
return;
}
this._tree.setFocus([item]);
const actions = menus.getResourceContextActions(item);
if (!actions.length) {
......
......@@ -43,6 +43,11 @@ export interface TimelineOptions {
limit?: number | string;
}
export interface InternalTimelineOptions {
cacheResults: boolean;
resetCache: boolean;
}
export interface Timeline {
source: string;
items: TimelineItem[];
......@@ -59,7 +64,7 @@ export interface Timeline {
export interface TimelineProvider extends TimelineProviderDescriptor, IDisposable {
onDidChange?: Event<TimelineChangeEvent>;
provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: { cacheResults?: boolean }): Promise<Timeline | undefined>;
provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: InternalTimelineOptions): Promise<Timeline | undefined>;
}
export interface TimelineProviderDescriptor {
......@@ -93,7 +98,7 @@ export interface ITimelineService {
getSources(): string[];
getTimeline(id: string, uri: URI, options: TimelineOptions, tokenSource: CancellationTokenSource, internalOptions?: { cacheResults?: boolean }): TimelineRequest | undefined;
getTimeline(id: string, uri: URI, options: TimelineOptions, tokenSource: CancellationTokenSource, internalOptions?: InternalTimelineOptions): TimelineRequest | undefined;
// refresh(fetch?: 'all' | 'more'): void;
reset(): void;
......
......@@ -9,7 +9,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
// import { basename } from 'vs/base/common/path';
import { URI } from 'vs/base/common/uri';
import { ILogService } from 'vs/platform/log/common/log';
import { ITimelineService, TimelineChangeEvent, TimelineOptions, TimelineProvidersChangeEvent, TimelineProvider } from './timeline';
import { ITimelineService, TimelineChangeEvent, TimelineOptions, TimelineProvidersChangeEvent, TimelineProvider, InternalTimelineOptions } from './timeline';
export class TimelineService implements ITimelineService {
_serviceBrand: undefined;
......@@ -27,54 +27,68 @@ export class TimelineService implements ITimelineService {
private readonly _providerSubscriptions = new Map<string, IDisposable>();
constructor(@ILogService private readonly logService: ILogService) {
// let source = 'slow-source';
// this.registerTimelineProvider({
// id: 'local-history',
// label: 'Local History',
// provideTimeline(uri: URI, token: CancellationToken) {
// scheme: '*',
// id: source,
// label: 'Slow Source',
// provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: { cacheResults?: boolean | undefined; }) {
// return new Promise(resolve => setTimeout(() => {
// resolve([
// {
// id: '1',
// label: 'Slow Timeline1',
// description: basename(uri.fsPath),
// timestamp: Date.now(),
// source: 'local-history'
// },
// {
// id: '2',
// label: 'Slow Timeline2',
// description: basename(uri.fsPath),
// timestamp: new Date(0).getTime(),
// source: 'local-history'
// }
// ]);
// }, 3000));
// resolve({
// source: source,
// items: [
// {
// handle: `${source}|1`,
// id: '1',
// label: 'Slow Timeline1',
// description: basename(uri.fsPath),
// timestamp: Date.now(),
// source: source
// },
// {
// handle: `${source}|2`,
// id: '2',
// label: 'Slow Timeline2',
// description: basename(uri.fsPath),
// timestamp: new Date(0).getTime(),
// source: source
// }
// ]
// });
// }, 5000));
// },
// dispose() { }
// });
// source = 'very-slow-source';
// this.registerTimelineProvider({
// id: 'slow-history',
// label: 'Slow History',
// provideTimeline(uri: URI, token: CancellationToken) {
// scheme: '*',
// id: source,
// label: 'Very Slow Source',
// provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: { cacheResults?: boolean | undefined; }) {
// return new Promise(resolve => setTimeout(() => {
// resolve([
// {
// id: '1',
// label: 'VERY Slow Timeline1',
// description: basename(uri.fsPath),
// timestamp: Date.now(),
// source: 'slow-history'
// },
// {
// id: '2',
// label: 'VERY Slow Timeline2',
// description: basename(uri.fsPath),
// timestamp: new Date(0).getTime(),
// source: 'slow-history'
// }
// ]);
// }, 6000));
// resolve({
// source: source,
// items: [
// {
// handle: `${source}|1`,
// id: '1',
// label: 'VERY Slow Timeline1',
// description: basename(uri.fsPath),
// timestamp: Date.now(),
// source: source
// },
// {
// handle: `${source}|2`,
// id: '2',
// label: 'VERY Slow Timeline2',
// description: basename(uri.fsPath),
// timestamp: new Date(0).getTime(),
// source: source
// }
// ]
// });
// }, 10000));
// },
// dispose() { }
// });
......@@ -84,7 +98,7 @@ export class TimelineService implements ITimelineService {
return [...this._providers.keys()];
}
getTimeline(id: string, uri: URI, options: TimelineOptions, tokenSource: CancellationTokenSource, internalOptions?: { cacheResults?: boolean }) {
getTimeline(id: string, uri: URI, options: TimelineOptions, tokenSource: CancellationTokenSource, internalOptions?: InternalTimelineOptions) {
this.logService.trace(`TimelineService#getTimeline(${id}): uri=${uri.toString(true)}`);
const provider = this._providers.get(id);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册