Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
afacd2bd
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
afacd2bd
编写于
3月 01, 2020
作者:
E
Eric Amodio
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixes #89509, #91464, #91628, #91619
上级
77dcee27
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
218 addition
and
148 deletion
+218
-148
src/vs/workbench/api/browser/mainThreadTimeline.ts
src/vs/workbench/api/browser/mainThreadTimeline.ts
+2
-2
src/vs/workbench/api/common/extHost.protocol.ts
src/vs/workbench/api/common/extHost.protocol.ts
+2
-2
src/vs/workbench/api/common/extHostTimeline.ts
src/vs/workbench/api/common/extHostTimeline.ts
+35
-54
src/vs/workbench/contrib/timeline/browser/media/timelinePane.css
...workbench/contrib/timeline/browser/media/timelinePane.css
+17
-1
src/vs/workbench/contrib/timeline/browser/timelinePane.ts
src/vs/workbench/contrib/timeline/browser/timelinePane.ts
+99
-45
src/vs/workbench/contrib/timeline/common/timeline.ts
src/vs/workbench/contrib/timeline/common/timeline.ts
+7
-2
src/vs/workbench/contrib/timeline/common/timelineService.ts
src/vs/workbench/contrib/timeline/common/timelineService.ts
+56
-42
未找到文件。
src/vs/workbench/api/browser/mainThreadTimeline.ts
浏览文件 @
afacd2bd
...
...
@@ -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
()
{
...
...
src/vs/workbench/api/common/extHost.protocol.ts
浏览文件 @
afacd2bd
...
...
@@ -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
...
...
src/vs/workbench/api/common/extHostTimeline.ts
浏览文件 @
afacd2bd
...
...
@@ -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
_itemsBySource
ByUriMap
=
new
Map
<
string
|
undefined
,
Map
<
string
,
Map
<
string
,
vscode
.
TimelineItem
>>>
();
private
_itemsBySource
AndUriMap
=
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
.
_itemsBySource
ByUriMap
.
get
(
getUriKey
(
uri
))?.
get
(
arg
.
source
)?.
get
(
arg
.
handle
);
return
this
.
_itemsBySource
AndUriMap
.
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
itemsBySource
ByUriMap
=
this
.
_itemsBySourceBy
UriMap
;
const
itemsBySource
AndUriMap
=
this
.
_itemsBySourceAnd
UriMap
;
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
++
}
`
}
`
;
items
Map
?.
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
.
_itemsBySource
By
UriMap
.
values
())
{
for
(
const
sourceMap
of
this
.
_itemsBySource
And
UriMap
.
values
())
{
sourceMap
.
get
(
provider
.
id
)?.
clear
();
}
...
...
src/vs/workbench/contrib/timeline/browser/media/timelinePane.css
浏览文件 @
afacd2bd
...
...
@@ -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
;
...
...
src/vs/workbench/contrib/timeline/browser/timelinePane.ts
浏览文件 @
afacd2bd
...
...
@@ -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
)
{
...
...
src/vs/workbench/contrib/timeline/common/timeline.ts
浏览文件 @
afacd2bd
...
...
@@ -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
;
...
...
src/vs/workbench/contrib/timeline/common/timelineService.ts
浏览文件 @
afacd2bd
...
...
@@ -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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录