Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
419d5bba
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,发现更多精彩内容 >>
提交
419d5bba
编写于
12月 17, 2018
作者:
J
Joao Moreno
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
AsyncDataTree<TInput...
related to #65091
上级
8c09d4f4
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
211 addition
and
203 deletion
+211
-203
src/vs/base/browser/ui/tree/asyncDataTree.ts
src/vs/base/browser/ui/tree/asyncDataTree.ts
+85
-67
src/vs/base/browser/ui/tree/dataTree.ts
src/vs/base/browser/ui/tree/dataTree.ts
+17
-13
src/vs/base/browser/ui/tree/tree.ts
src/vs/base/browser/ui/tree/tree.ts
+3
-3
src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts
src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts
+6
-10
src/vs/editor/contrib/referenceSearch/referencesTree.ts
src/vs/editor/contrib/referenceSearch/referencesTree.ts
+9
-16
src/vs/editor/contrib/referenceSearch/referencesWidget.ts
src/vs/editor/contrib/referenceSearch/referencesWidget.ts
+6
-8
src/vs/platform/list/browser/listService.ts
src/vs/platform/list/browser/listService.ts
+4
-4
src/vs/workbench/browser/viewlet.ts
src/vs/workbench/browser/viewlet.ts
+1
-1
src/vs/workbench/parts/debug/browser/debugActions.ts
src/vs/workbench/parts/debug/browser/debugActions.ts
+1
-1
src/vs/workbench/parts/debug/browser/loadedScriptsView.ts
src/vs/workbench/parts/debug/browser/loadedScriptsView.ts
+9
-13
src/vs/workbench/parts/debug/electron-browser/callStackView.ts
...s/workbench/parts/debug/electron-browser/callStackView.ts
+22
-19
src/vs/workbench/parts/debug/electron-browser/debugHover.ts
src/vs/workbench/parts/debug/electron-browser/debugHover.ts
+6
-13
src/vs/workbench/parts/debug/electron-browser/repl.ts
src/vs/workbench/parts/debug/electron-browser/repl.ts
+7
-5
src/vs/workbench/parts/debug/electron-browser/variablesView.ts
...s/workbench/parts/debug/electron-browser/variablesView.ts
+18
-13
src/vs/workbench/parts/debug/electron-browser/watchExpressionsView.ts
...ench/parts/debug/electron-browser/watchExpressionsView.ts
+17
-17
未找到文件。
src/vs/base/browser/ui/tree/asyncDataTree.ts
浏览文件 @
419d5bba
...
...
@@ -21,11 +21,11 @@ enum AsyncDataTreeNodeState {
Slow
}
interface
IAsyncDataTreeNode
<
T
extends
NonNullable
<
any
>
>
{
element
:
T
|
null
;
readonly
parent
:
IAsyncDataTreeNode
<
T
>
|
null
;
interface
IAsyncDataTreeNode
<
T
Input
,
T
>
{
element
:
T
Input
|
T
;
readonly
parent
:
IAsyncDataTreeNode
<
T
Input
,
T
>
|
null
;
readonly
id
?:
string
|
null
;
readonly
children
?:
IAsyncDataTreeNode
<
T
>
[];
readonly
children
?:
IAsyncDataTreeNode
<
T
Input
,
T
>
[];
state
:
AsyncDataTreeNodeState
;
}
...
...
@@ -33,9 +33,9 @@ interface IDataTreeListTemplateData<T> {
templateData
:
T
;
}
class
AsyncDataTreeNodeWrapper
<
T
,
TFilterData
>
implements
ITreeNode
<
T
,
TFilterData
>
{
class
AsyncDataTreeNodeWrapper
<
T
Input
,
T
,
TFilterData
>
implements
ITreeNode
<
TInput
|
T
,
TFilterData
>
{
get
element
():
T
{
return
this
.
node
.
element
!
.
element
!
;
}
get
element
():
T
{
return
this
.
node
.
element
!
.
element
as
T
;
}
get
parent
():
ITreeNode
<
T
,
TFilterData
>
|
undefined
{
return
this
.
node
.
parent
&&
new
AsyncDataTreeNodeWrapper
(
this
.
node
.
parent
);
}
get
children
():
ITreeNode
<
T
,
TFilterData
>
[]
{
return
this
.
node
.
children
.
map
(
node
=>
new
AsyncDataTreeNodeWrapper
(
node
));
}
get
depth
():
number
{
return
this
.
node
.
depth
;
}
...
...
@@ -44,18 +44,18 @@ class AsyncDataTreeNodeWrapper<T, TFilterData> implements ITreeNode<T, TFilterDa
get
visible
():
boolean
{
return
this
.
node
.
visible
;
}
get
filterData
():
TFilterData
|
undefined
{
return
this
.
node
.
filterData
;
}
constructor
(
private
node
:
ITreeNode
<
IAsyncDataTreeNode
<
T
>
|
null
,
TFilterData
>
)
{
}
constructor
(
private
node
:
ITreeNode
<
IAsyncDataTreeNode
<
T
Input
,
T
>
|
null
,
TFilterData
>
)
{
}
}
class
DataTreeRenderer
<
T
,
TFilterData
,
TTemplateData
>
implements
ITreeRenderer
<
IAsyncDataTreeNode
<
T
>
,
TFilterData
,
IDataTreeListTemplateData
<
TTemplateData
>>
{
class
DataTreeRenderer
<
T
Input
,
T
,
TFilterData
,
TTemplateData
>
implements
ITreeRenderer
<
IAsyncDataTreeNode
<
TInput
,
T
>
,
TFilterData
,
IDataTreeListTemplateData
<
TTemplateData
>>
{
readonly
templateId
:
string
;
private
renderedNodes
=
new
Map
<
IAsyncDataTreeNode
<
T
>
,
IDataTreeListTemplateData
<
TTemplateData
>>
();
private
renderedNodes
=
new
Map
<
IAsyncDataTreeNode
<
T
Input
,
T
>
,
IDataTreeListTemplateData
<
TTemplateData
>>
();
private
disposables
:
IDisposable
[]
=
[];
constructor
(
private
renderer
:
ITreeRenderer
<
T
,
TFilterData
,
TTemplateData
>
,
readonly
onDidChangeTwistieState
:
Event
<
IAsyncDataTreeNode
<
T
>>
readonly
onDidChangeTwistieState
:
Event
<
IAsyncDataTreeNode
<
T
Input
,
T
>>
)
{
this
.
templateId
=
renderer
.
templateId
;
}
...
...
@@ -65,16 +65,16 @@ class DataTreeRenderer<T, TFilterData, TTemplateData> implements ITreeRenderer<I
return
{
templateData
};
}
renderElement
(
node
:
ITreeNode
<
IAsyncDataTreeNode
<
T
>
,
TFilterData
>
,
index
:
number
,
templateData
:
IDataTreeListTemplateData
<
TTemplateData
>
):
void
{
renderElement
(
node
:
ITreeNode
<
IAsyncDataTreeNode
<
T
Input
,
T
>
,
TFilterData
>
,
index
:
number
,
templateData
:
IDataTreeListTemplateData
<
TTemplateData
>
):
void
{
this
.
renderer
.
renderElement
(
new
AsyncDataTreeNodeWrapper
(
node
),
index
,
templateData
.
templateData
);
}
renderTwistie
(
element
:
IAsyncDataTreeNode
<
T
>
,
twistieElement
:
HTMLElement
):
boolean
{
renderTwistie
(
element
:
IAsyncDataTreeNode
<
T
Input
,
T
>
,
twistieElement
:
HTMLElement
):
boolean
{
toggleClass
(
twistieElement
,
'
loading
'
,
element
.
state
===
AsyncDataTreeNodeState
.
Slow
);
return
false
;
}
disposeElement
(
node
:
ITreeNode
<
IAsyncDataTreeNode
<
T
>
,
TFilterData
>
,
index
:
number
,
templateData
:
IDataTreeListTemplateData
<
TTemplateData
>
):
void
{
disposeElement
(
node
:
ITreeNode
<
IAsyncDataTreeNode
<
T
Input
,
T
>
,
TFilterData
>
,
index
:
number
,
templateData
:
IDataTreeListTemplateData
<
TTemplateData
>
):
void
{
if
(
this
.
renderer
.
disposeElement
)
{
this
.
renderer
.
disposeElement
(
new
AsyncDataTreeNodeWrapper
(
node
),
index
,
templateData
.
templateData
);
}
...
...
@@ -90,24 +90,24 @@ class DataTreeRenderer<T, TFilterData, TTemplateData> implements ITreeRenderer<I
}
}
function
asTreeEvent
<
T
>
(
e
:
ITreeEvent
<
IAsyncDataTreeNode
<
T
>>
):
ITreeEvent
<
T
>
{
function
asTreeEvent
<
T
Input
,
T
>
(
e
:
ITreeEvent
<
IAsyncDataTreeNode
<
TInput
,
T
>>
):
ITreeEvent
<
T
>
{
return
{
browserEvent
:
e
.
browserEvent
,
elements
:
e
.
elements
.
map
(
e
=>
e
.
element
!
)
elements
:
e
.
elements
.
map
(
e
=>
e
.
element
as
T
)
};
}
function
asTreeMouseEvent
<
T
>
(
e
:
ITreeMouseEvent
<
IAsyncDataTreeNode
<
T
>>
):
ITreeMouseEvent
<
T
>
{
function
asTreeMouseEvent
<
T
Input
,
T
>
(
e
:
ITreeMouseEvent
<
IAsyncDataTreeNode
<
TInput
,
T
>>
):
ITreeMouseEvent
<
T
>
{
return
{
browserEvent
:
e
.
browserEvent
,
element
:
e
.
element
&&
e
.
element
.
element
!
element
:
e
.
element
&&
e
.
element
.
element
as
T
};
}
function
asTreeContextMenuEvent
<
T
>
(
e
:
ITreeContextMenuEvent
<
IAsyncDataTreeNode
<
T
>>
):
ITreeContextMenuEvent
<
T
>
{
function
asTreeContextMenuEvent
<
T
Input
,
T
>
(
e
:
ITreeContextMenuEvent
<
IAsyncDataTreeNode
<
TInput
,
T
>>
):
ITreeContextMenuEvent
<
T
>
{
return
{
browserEvent
:
e
.
browserEvent
,
element
:
e
.
element
&&
e
.
element
.
element
!
,
element
:
e
.
element
&&
e
.
element
.
element
as
T
,
anchor
:
e
.
anchor
};
}
...
...
@@ -122,12 +122,12 @@ export interface IChildrenResolutionEvent<T> {
readonly
reason
:
ChildrenResolutionReason
;
}
function
asObjectTreeOptions
<
T
,
TFilterData
>
(
options
?:
IAsyncDataTreeOptions
<
T
,
TFilterData
>
):
IObjectTreeOptions
<
IAsyncDataTreeNode
<
T
>
,
TFilterData
>
|
undefined
{
function
asObjectTreeOptions
<
T
Input
,
T
,
TFilterData
>
(
options
?:
IAsyncDataTreeOptions
<
T
,
TFilterData
>
):
IObjectTreeOptions
<
IAsyncDataTreeNode
<
TInput
,
T
>
,
TFilterData
>
|
undefined
{
return
options
&&
{
...
options
,
identityProvider
:
options
.
identityProvider
&&
{
getId
(
el
)
{
return
options
.
identityProvider
!
.
getId
(
el
.
element
!
);
return
options
.
identityProvider
!
.
getId
(
el
.
element
as
T
);
}
},
multipleSelectionController
:
options
.
multipleSelectionController
&&
{
...
...
@@ -140,28 +140,28 @@ function asObjectTreeOptions<T, TFilterData>(options?: IAsyncDataTreeOptions<T,
},
accessibilityProvider
:
options
.
accessibilityProvider
&&
{
getAriaLabel
(
e
)
{
return
options
.
accessibilityProvider
!
.
getAriaLabel
(
e
.
element
!
);
return
options
.
accessibilityProvider
!
.
getAriaLabel
(
e
.
element
as
T
);
}
},
filter
:
options
.
filter
&&
{
filter
(
e
,
parentVisibility
)
{
return
options
.
filter
!
.
filter
(
e
.
element
!
,
parentVisibility
);
return
options
.
filter
!
.
filter
(
e
.
element
as
T
,
parentVisibility
);
}
},
keyboardNavigationLabelProvider
:
options
.
keyboardNavigationLabelProvider
&&
{
getKeyboardNavigationLabel
(
e
)
{
return
options
.
keyboardNavigationLabelProvider
!
.
getKeyboardNavigationLabel
(
e
.
element
!
);
return
options
.
keyboardNavigationLabelProvider
!
.
getKeyboardNavigationLabel
(
e
.
element
as
T
);
}
},
sorter
:
options
.
sorter
&&
{
compare
(
a
,
b
)
{
return
options
.
sorter
!
.
compare
(
a
.
element
!
,
b
.
element
!
);
return
options
.
sorter
!
.
compare
(
a
.
element
as
T
,
b
.
element
as
T
);
}
}
};
}
function
asTreeElement
<
T
>
(
node
:
IAsyncDataTreeNode
<
T
>
):
ITreeElement
<
IAsyncDataTreeNode
<
T
>>
{
function
asTreeElement
<
T
Input
,
T
>
(
node
:
IAsyncDataTreeNode
<
TInput
,
T
>
):
ITreeElement
<
IAsyncDataTreeNode
<
TInput
,
T
>>
{
return
{
element
:
node
,
children
:
Iterator
.
map
(
Iterator
.
fromArray
(
node
.
children
!
),
asTreeElement
)
...
...
@@ -173,15 +173,15 @@ export interface IAsyncDataTreeOptions<T, TFilterData = void> extends IAbstractT
sorter
?:
ITreeSorter
<
T
>
;
}
export
class
AsyncDataTree
<
T
extends
NonNullable
<
any
>
,
TFilterData
=
void
>
implements
IDisposable
{
export
class
AsyncDataTree
<
T
Input
,
T
,
TFilterData
=
void
>
implements
IDisposable
{
private
readonly
tree
:
ObjectTree
<
IAsyncDataTreeNode
<
T
>
,
TFilterData
>
;
private
readonly
root
:
IAsyncDataTreeNode
<
T
>
;
private
readonly
nodes
=
new
Map
<
T
|
null
,
IAsyncDataTreeNode
<
T
>>
();
private
readonly
refreshPromises
=
new
Map
<
IAsyncDataTreeNode
<
T
>
,
Promise
<
void
>>
();
private
readonly
tree
:
ObjectTree
<
IAsyncDataTreeNode
<
T
Input
,
T
>
,
TFilterData
>
;
private
readonly
root
:
IAsyncDataTreeNode
<
T
Input
,
T
>
;
private
readonly
nodes
=
new
Map
<
null
|
T
,
IAsyncDataTreeNode
<
TInput
,
T
>>
();
private
readonly
refreshPromises
=
new
Map
<
IAsyncDataTreeNode
<
T
Input
,
T
>
,
Promise
<
void
>>
();
private
readonly
identityProvider
?:
IIdentityProvider
<
T
>
;
private
readonly
_onDidChangeNodeState
=
new
Emitter
<
IAsyncDataTreeNode
<
T
>>
();
private
readonly
_onDidChangeNodeState
=
new
Emitter
<
IAsyncDataTreeNode
<
T
Input
,
T
>>
();
protected
readonly
disposables
:
IDisposable
[]
=
[];
...
...
@@ -204,20 +204,20 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
container
:
HTMLElement
,
delegate
:
IListVirtualDelegate
<
T
>
,
renderers
:
ITreeRenderer
<
any
/* TODO@joao */
,
TFilterData
,
any
>
[],
private
dataSource
:
IAsyncDataSource
<
T
>
,
private
dataSource
:
IAsyncDataSource
<
T
Input
,
T
>
,
options
?:
IAsyncDataTreeOptions
<
T
,
TFilterData
>
)
{
this
.
identityProvider
=
options
&&
options
.
identityProvider
;
const
objectTreeDelegate
=
new
ComposedTreeDelegate
<
T
|
null
,
IAsyncDataTreeNode
<
T
>>
(
delegate
);
const
objectTreeDelegate
=
new
ComposedTreeDelegate
<
T
Input
|
T
,
IAsyncDataTreeNode
<
TInput
,
T
>>
(
delegate
);
const
objectTreeRenderers
=
renderers
.
map
(
r
=>
new
DataTreeRenderer
(
r
,
this
.
_onDidChangeNodeState
.
event
));
const
objectTreeOptions
=
asObjectTreeOptions
(
options
)
||
{};
const
objectTreeOptions
=
asObjectTreeOptions
<
TInput
,
T
,
TFilterData
>
(
options
)
||
{};
objectTreeOptions
.
collapseByDefault
=
true
;
this
.
tree
=
new
ObjectTree
(
container
,
objectTreeDelegate
,
objectTreeRenderers
,
objectTreeOptions
);
this
.
root
=
{
element
:
null
,
element
:
undefined
!
,
parent
:
null
,
state
:
AsyncDataTreeNodeState
.
Uninitialized
,
};
...
...
@@ -279,16 +279,34 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
// Data Tree
refresh
(
element
:
T
|
null
,
recursive
=
true
):
Promise
<
void
>
{
getInput
():
TInput
|
undefined
{
return
this
.
root
.
element
as
TInput
;
}
setInput
(
input
:
TInput
|
undefined
):
Promise
<
void
>
{
this
.
root
.
element
=
input
!
;
if
(
typeof
input
===
'
undefined
'
)
{
return
Promise
.
resolve
();
}
return
this
.
refresh
(
input
);
}
refresh
(
element
:
TInput
|
T
=
this
.
root
.
element
,
recursive
=
true
):
Promise
<
void
>
{
if
(
typeof
this
.
root
.
element
===
'
undefined
'
)
{
throw
new
Error
(
'
Tree input not set
'
);
}
return
this
.
refreshNode
(
this
.
getDataNode
(
element
),
recursive
,
ChildrenResolutionReason
.
Refresh
);
}
// Tree
getNode
(
element
:
T
|
null
):
ITreeNode
<
T
|
null
,
TFilterData
>
{
getNode
(
element
:
T
Input
|
T
):
ITreeNode
<
TInput
|
T
,
TFilterData
>
{
const
dataNode
=
this
.
getDataNode
(
element
);
const
node
=
this
.
tree
.
getNode
(
dataNode
===
this
.
root
?
null
:
dataNode
);
return
new
AsyncDataTreeNodeWrapper
<
T
|
null
,
TFilterData
>
(
node
);
return
new
AsyncDataTreeNodeWrapper
<
T
Input
,
T
,
TFilterData
>
(
node
);
}
collapse
(
element
:
T
,
recursive
:
boolean
=
false
):
boolean
{
...
...
@@ -342,7 +360,7 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
getSelection
():
T
[]
{
const
nodes
=
this
.
tree
.
getSelection
();
return
nodes
.
map
(
n
=>
n
!
.
element
!
);
return
nodes
.
map
(
n
=>
n
!
.
element
as
T
);
}
setFocus
(
elements
:
T
[],
browserEvent
?:
UIEvent
):
void
{
...
...
@@ -376,7 +394,7 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
getFocus
():
T
[]
{
const
nodes
=
this
.
tree
.
getFocus
();
return
nodes
.
map
(
n
=>
n
!
.
element
!
);
return
nodes
.
map
(
n
=>
n
!
.
element
as
T
);
}
open
(
elements
:
T
[]):
void
{
...
...
@@ -394,21 +412,21 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
// Tree navigation
getParentElement
(
element
:
T
):
T
|
null
{
getParentElement
(
element
:
T
):
T
Input
|
T
{
const
node
=
this
.
tree
.
getParentElement
(
this
.
getDataNode
(
element
));
return
node
&&
node
.
element
;
return
(
node
&&
node
.
element
)
!
;
}
getFirstElementChild
(
element
:
T
|
null
=
null
):
T
|
null
|
undefined
{
getFirstElementChild
(
element
:
T
Input
|
T
=
this
.
root
.
element
):
TInput
|
T
|
undefined
{
const
dataNode
=
this
.
getDataNode
(
element
);
const
node
=
this
.
tree
.
getFirstElementChild
(
dataNode
===
this
.
root
?
null
:
dataNode
);
return
node
&&
node
.
element
;
return
(
node
&&
node
.
element
)
!
;
}
getLastElementAncestor
(
element
:
T
|
null
=
null
):
T
|
null
|
undefined
{
getLastElementAncestor
(
element
:
T
Input
|
T
=
this
.
root
.
element
):
TInput
|
T
|
undefined
{
const
dataNode
=
this
.
getDataNode
(
element
);
const
node
=
this
.
tree
.
getLastElementAncestor
(
dataNode
===
this
.
root
?
null
:
dataNode
);
return
node
&&
node
.
element
;
return
(
node
&&
node
.
element
)
!
;
}
// List
...
...
@@ -419,8 +437,8 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
// Implementation
private
getDataNode
(
element
:
T
|
null
):
IAsyncDataTreeNode
<
T
>
{
const
node
:
IAsyncDataTreeNode
<
T
>
=
this
.
nodes
.
get
(
element
);
private
getDataNode
(
element
:
T
Input
|
T
):
IAsyncDataTreeNode
<
TInput
,
T
>
{
const
node
:
IAsyncDataTreeNode
<
T
Input
,
T
>
=
this
.
nodes
.
get
((
element
===
this
.
root
.
element
?
null
:
element
)
as
T
);
if
(
typeof
node
===
'
undefined
'
)
{
throw
new
Error
(
`Data tree node not found:
${
element
}
`
);
...
...
@@ -429,7 +447,7 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
return
node
;
}
private
async
refreshNode
(
node
:
IAsyncDataTreeNode
<
T
>
,
recursive
:
boolean
,
reason
:
ChildrenResolutionReason
):
Promise
<
void
>
{
private
async
refreshNode
(
node
:
IAsyncDataTreeNode
<
T
Input
,
T
>
,
recursive
:
boolean
,
reason
:
ChildrenResolutionReason
):
Promise
<
void
>
{
await
this
.
_refreshNode
(
node
,
recursive
,
reason
);
if
(
recursive
&&
node
.
children
)
{
...
...
@@ -437,7 +455,7 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
}
}
private
_refreshNode
(
node
:
IAsyncDataTreeNode
<
T
>
,
recursive
:
boolean
,
reason
:
ChildrenResolutionReason
):
Promise
<
void
>
{
private
_refreshNode
(
node
:
IAsyncDataTreeNode
<
T
Input
,
T
>
,
recursive
:
boolean
,
reason
:
ChildrenResolutionReason
):
Promise
<
void
>
{
let
result
=
this
.
refreshPromises
.
get
(
node
);
if
(
result
)
{
...
...
@@ -449,8 +467,8 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
return
always
(
result
,
()
=>
this
.
refreshPromises
.
delete
(
node
));
}
private
doRefresh
(
node
:
IAsyncDataTreeNode
<
T
>
,
recursive
:
boolean
,
reason
:
ChildrenResolutionReason
):
Promise
<
void
>
{
const
hasChildren
=
!!
this
.
dataSource
.
hasChildren
(
node
.
element
);
private
doRefresh
(
node
:
IAsyncDataTreeNode
<
T
Input
,
T
>
,
recursive
:
boolean
,
reason
:
ChildrenResolutionReason
):
Promise
<
void
>
{
const
hasChildren
=
!!
this
.
dataSource
.
hasChildren
(
node
.
element
!
);
if
(
!
hasChildren
)
{
this
.
setChildren
(
node
,
[],
recursive
);
...
...
@@ -468,14 +486,14 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
this
.
_onDidChangeNodeState
.
fire
(
node
);
},
_
=>
null
);
return
Promise
.
resolve
(
this
.
dataSource
.
getChildren
(
node
.
element
))
return
Promise
.
resolve
(
this
.
dataSource
.
getChildren
(
node
.
element
!
))
.
then
(
children
=>
{
slowTimeout
.
cancel
();
node
.
state
=
AsyncDataTreeNodeState
.
Loaded
;
this
.
_onDidChangeNodeState
.
fire
(
node
);
this
.
setChildren
(
node
,
children
,
recursive
);
this
.
_onDidResolveChildren
.
fire
({
element
:
node
.
element
,
reason
});
this
.
_onDidResolveChildren
.
fire
({
element
:
node
.
element
as
T
,
reason
});
},
err
=>
{
slowTimeout
.
cancel
();
node
.
state
=
AsyncDataTreeNodeState
.
Uninitialized
;
...
...
@@ -490,18 +508,18 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
}
}
private
_onDidChangeCollapseState
({
node
,
deep
}:
ICollapseStateChangeEvent
<
IAsyncDataTreeNode
<
T
>
,
any
>
):
void
{
private
_onDidChangeCollapseState
({
node
,
deep
}:
ICollapseStateChangeEvent
<
IAsyncDataTreeNode
<
T
Input
,
T
>
,
any
>
):
void
{
if
(
!
node
.
collapsed
&&
node
.
element
.
state
===
AsyncDataTreeNodeState
.
Uninitialized
)
{
if
(
deep
)
{
this
.
collapse
(
node
.
element
.
element
!
);
this
.
collapse
(
node
.
element
.
element
as
T
);
}
else
{
this
.
refreshNode
(
node
.
element
,
false
,
ChildrenResolutionReason
.
Expand
);
}
}
}
private
setChildren
(
node
:
IAsyncDataTreeNode
<
T
>
,
childrenElements
:
T
[],
recursive
:
boolean
):
void
{
const
children
=
childrenElements
.
map
<
ITreeElement
<
IAsyncDataTreeNode
<
T
>>>
(
element
=>
{
private
setChildren
(
node
:
IAsyncDataTreeNode
<
T
Input
,
T
>
,
childrenElements
:
T
[],
recursive
:
boolean
):
void
{
const
children
=
childrenElements
.
map
<
ITreeElement
<
IAsyncDataTreeNode
<
T
Input
,
T
>>>
(
element
=>
{
if
(
!
this
.
identityProvider
)
{
return
{
element
:
{
...
...
@@ -514,7 +532,7 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
};
}
const
nodeChildren
=
new
Map
<
string
,
IAsyncDataTreeNode
<
T
>>
();
const
nodeChildren
=
new
Map
<
string
,
IAsyncDataTreeNode
<
T
Input
,
T
>>
();
for
(
const
child
of
node
.
children
!
)
{
nodeChildren
.
set
(
child
.
id
!
,
child
);
...
...
@@ -556,7 +574,7 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
}
}
let
children
:
Iterator
<
ITreeElement
<
IAsyncDataTreeNode
<
T
>>>
|
undefined
=
undefined
;
let
children
:
Iterator
<
ITreeElement
<
IAsyncDataTreeNode
<
T
Input
,
T
>>>
|
undefined
=
undefined
;
if
(
collapsible
)
{
children
=
Iterator
.
map
(
Iterator
.
fromArray
(
asyncDataTreeNode
.
children
!
),
asTreeElement
);
...
...
@@ -572,17 +590,17 @@ export class AsyncDataTree<T extends NonNullable<any>, TFilterData = void> imple
const
insertedElements
=
new
Set
<
T
>
();
const
onDidCreateNode
=
(
treeNode
:
ITreeNode
<
IAsyncDataTreeNode
<
T
>
,
TFilterData
>
)
=>
{
const
onDidCreateNode
=
(
treeNode
:
ITreeNode
<
IAsyncDataTreeNode
<
T
Input
,
T
>
,
TFilterData
>
)
=>
{
if
(
treeNode
.
element
.
element
)
{
insertedElements
.
add
(
treeNode
.
element
.
element
);
this
.
nodes
.
set
(
treeNode
.
element
.
element
,
treeNode
.
element
);
insertedElements
.
add
(
treeNode
.
element
.
element
as
T
);
this
.
nodes
.
set
(
treeNode
.
element
.
element
as
T
,
treeNode
.
element
);
}
};
const
onDidDeleteNode
=
(
treeNode
:
ITreeNode
<
IAsyncDataTreeNode
<
T
>
,
TFilterData
>
)
=>
{
const
onDidDeleteNode
=
(
treeNode
:
ITreeNode
<
IAsyncDataTreeNode
<
T
Input
,
T
>
,
TFilterData
>
)
=>
{
if
(
treeNode
.
element
.
element
)
{
if
(
!
insertedElements
.
has
(
treeNode
.
element
.
element
))
{
this
.
nodes
.
delete
(
treeNode
.
element
.
element
);
if
(
!
insertedElements
.
has
(
treeNode
.
element
.
element
as
T
))
{
this
.
nodes
.
delete
(
treeNode
.
element
.
element
as
T
);
}
}
};
...
...
src/vs/base/browser/ui/tree/dataTree.ts
浏览文件 @
419d5bba
...
...
@@ -17,17 +17,7 @@ export interface IDataTreeOptions<T, TFilterData = void> extends IAbstractTreeOp
export
class
DataTree
<
TInput
,
T
,
TFilterData
=
void
>
extends
AbstractTree
<
T
|
null
,
TFilterData
,
TInput
|
T
>
{
protected
model
:
ObjectTreeModel
<
T
|
null
,
TFilterData
>
;
private
_input
:
TInput
|
undefined
;
get
input
():
TInput
|
undefined
{
return
this
.
_input
;
}
set
input
(
input
:
TInput
|
undefined
)
{
this
.
_input
=
input
;
this
.
refresh
(
input
);
}
private
input
:
TInput
|
undefined
;
constructor
(
container
:
HTMLElement
,
...
...
@@ -39,8 +29,22 @@ export class DataTree<TInput, T, TFilterData = void> extends AbstractTree<T | nu
super
(
container
,
delegate
,
renderers
,
options
);
}
refresh
(
element
:
TInput
|
T
):
void
{
if
(
!
this
.
_input
)
{
getInput
():
TInput
|
undefined
{
return
this
.
input
;
}
setInput
(
input
:
TInput
|
undefined
):
void
{
this
.
input
=
input
;
if
(
typeof
input
===
'
undefined
'
)
{
return
;
}
this
.
refresh
(
input
);
}
refresh
(
element
:
TInput
|
T
=
this
.
input
):
void
{
if
(
typeof
this
.
input
===
'
undefined
'
)
{
throw
new
Error
(
'
Tree input not set
'
);
}
...
...
src/vs/base/browser/ui/tree/tree.ts
浏览文件 @
419d5bba
...
...
@@ -149,9 +149,9 @@ export interface IDataSource<TInput, T> {
getChildren
(
element
:
TInput
|
T
):
T
[];
}
export
interface
IAsyncDataSource
<
T
extends
NonNullable
<
any
>
>
{
hasChildren
(
element
:
T
|
null
):
boolean
;
getChildren
(
element
:
T
|
null
):
T
[]
|
Promise
<
T
[]
>
;
export
interface
IAsyncDataSource
<
T
Input
,
T
>
{
hasChildren
(
element
:
T
Input
|
T
):
boolean
;
getChildren
(
element
:
T
Input
|
T
):
T
[]
|
Promise
<
T
[]
>
;
}
/**
...
...
src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts
浏览文件 @
419d5bba
...
...
@@ -51,15 +51,11 @@ suite('AsyncDataTree', function () {
}
};
const
dataSource
=
new
class
implements
IAsyncDataSource
<
Element
>
{
hasChildren
(
element
:
Element
|
null
):
boolean
{
return
!
element
||
(
element
.
children
&&
element
.
children
.
length
>
0
)
;
const
dataSource
=
new
class
implements
IAsyncDataSource
<
Element
,
Element
>
{
hasChildren
(
element
:
Element
):
boolean
{
return
element
.
children
&&
element
.
children
.
length
>
0
;
}
getChildren
(
element
:
Element
|
null
):
Promise
<
Element
[]
>
{
if
(
!
element
)
{
return
Promise
.
resolve
(
root
.
children
);
}
getChildren
(
element
:
Element
):
Promise
<
Element
[]
>
{
return
Promise
.
resolve
(
element
.
children
||
[]);
}
};
...
...
@@ -79,11 +75,11 @@ suite('AsyncDataTree', function () {
const
_
:
(
id
:
string
)
=>
Element
=
find
.
bind
(
null
,
root
.
children
);
const
tree
=
new
AsyncDataTree
(
container
,
delegate
,
[
renderer
],
dataSource
,
{
identityProvider
});
const
tree
=
new
AsyncDataTree
<
Element
,
Element
>
(
container
,
delegate
,
[
renderer
],
dataSource
,
{
identityProvider
});
tree
.
layout
(
200
);
assert
.
equal
(
container
.
querySelectorAll
(
'
.monaco-list-row
'
).
length
,
0
);
await
tree
.
refresh
(
null
);
await
tree
.
setInput
(
root
);
assert
.
equal
(
container
.
querySelectorAll
(
'
.monaco-list-row
'
).
length
,
1
);
let
twistie
=
container
.
querySelector
(
'
.monaco-list-row:first-child .monaco-tl-twistie
'
)
as
HTMLElement
;
assert
(
!
hasClass
(
twistie
,
'
collapsible
'
));
...
...
src/vs/editor/contrib/referenceSearch/referencesTree.ts
浏览文件 @
419d5bba
...
...
@@ -26,18 +26,12 @@ import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
export
type
TreeElement
=
FileReferences
|
OneReference
;
export
class
DataSource
implements
IAsyncDataSource
<
TreeElement
>
{
export
class
DataSource
implements
IAsyncDataSource
<
ReferencesModel
|
FileReferences
,
TreeElement
>
{
root
:
ReferencesModel
|
FileReferences
;
constructor
(@
ITextModelService
private
readonly
_resolverService
:
ITextModelService
)
{
}
constructor
(
@
ITextModelService
private
readonly
_resolverService
:
ITextModelService
,
)
{
//
}
hasChildren
(
element
:
TreeElement
):
boolean
{
if
(
!
element
)
{
hasChildren
(
element
:
ReferencesModel
|
FileReferences
|
TreeElement
):
boolean
{
if
(
element
instanceof
ReferencesModel
)
{
return
true
;
}
if
(
element
instanceof
FileReferences
&&
!
element
.
failure
)
{
...
...
@@ -46,10 +40,11 @@ export class DataSource implements IAsyncDataSource<TreeElement> {
return
false
;
}
getChildren
(
element
:
TreeElement
):
Promise
<
TreeElement
[]
>
{
if
(
!
element
&&
this
.
root
instanceof
FileReferences
)
{
element
=
this
.
root
;
getChildren
(
element
:
ReferencesModel
|
FileReferences
|
TreeElement
):
TreeElement
[]
|
Promise
<
TreeElement
[]
>
{
if
(
element
instanceof
ReferencesModel
)
{
return
element
.
groups
;
}
if
(
element
instanceof
FileReferences
)
{
return
element
.
resolve
(
this
.
_resolverService
).
then
(
val
=>
{
// if (element.failure) {
...
...
@@ -60,9 +55,7 @@ export class DataSource implements IAsyncDataSource<TreeElement> {
return
val
.
children
;
});
}
if
(
this
.
root
instanceof
ReferencesModel
)
{
return
Promise
.
resolve
(
this
.
root
.
groups
);
}
throw
new
Error
(
'
bad tree
'
);
}
}
...
...
src/vs/editor/contrib/referenceSearch/referencesWidget.ts
浏览文件 @
419d5bba
...
...
@@ -237,8 +237,7 @@ export class ReferenceWidget extends PeekViewWidget {
private
_callOnDispose
:
IDisposable
[]
=
[];
private
_onDidSelectReference
=
new
Emitter
<
SelectionEvent
>
();
private
_treeDataSource
:
DataSource
;
private
_tree
:
WorkbenchAsyncDataTree
<
TreeElement
>
;
private
_tree
:
WorkbenchAsyncDataTree
<
ReferencesModel
|
FileReferences
,
TreeElement
>
;
private
_treeContainer
:
HTMLElement
;
private
_sash
:
VSash
;
private
_preview
:
ICodeEditor
;
...
...
@@ -357,14 +356,14 @@ export class ReferenceWidget extends PeekViewWidget {
accessibilityProvider
:
new
AriaProvider
()
};
this
.
_
treeDataSource
=
this
.
_instantiationService
.
createInstance
(
DataSource
);
const
treeDataSource
=
this
.
_instantiationService
.
createInstance
(
DataSource
);
this
.
_tree
=
this
.
_instantiationService
.
createInstance
<
HTMLElement
,
IListVirtualDelegate
<
TreeElement
>
,
ITreeRenderer
<
any
,
void
,
any
>
[],
IAsyncDataSource
<
TreeElement
>
,
IAsyncDataTreeOptions
<
TreeElement
,
void
>
,
WorkbenchAsyncDataTree
<
TreeElement
,
void
>>
(
this
.
_tree
=
this
.
_instantiationService
.
createInstance
<
HTMLElement
,
IListVirtualDelegate
<
TreeElement
>
,
ITreeRenderer
<
any
,
void
,
any
>
[],
IAsyncDataSource
<
ReferencesModel
|
FileReferences
,
TreeElement
>
,
IAsyncDataTreeOptions
<
TreeElement
,
void
>
,
WorkbenchAsyncDataTree
<
ReferencesModel
|
FileReferences
,
TreeElement
,
void
>>
(
WorkbenchAsyncDataTree
,
this
.
_treeContainer
,
new
Delegate
(),
renderers
,
t
his
.
_t
reeDataSource
,
treeDataSource
,
treeOptions
);
...
...
@@ -498,8 +497,7 @@ export class ReferenceWidget extends PeekViewWidget {
this
.
focus
();
// pick input and a reference to begin with
this
.
_treeDataSource
.
root
=
this
.
_model
.
groups
.
length
===
1
?
this
.
_model
.
groups
[
0
]
:
this
.
_model
;
return
this
.
_tree
.
refresh
(
null
);
return
this
.
_tree
.
setInput
(
this
.
_model
.
groups
.
length
===
1
?
this
.
_model
.
groups
[
0
]
:
this
.
_model
);
}
private
_getFocusedReference
():
OneReference
{
...
...
@@ -533,7 +531,7 @@ export class ReferenceWidget extends PeekViewWidget {
const
promise
=
this
.
_textModelResolverService
.
createModelReference
(
reference
.
uri
);
if
(
this
.
_tree
DataSource
.
root
===
reference
.
parent
)
{
if
(
this
.
_tree
.
getInput
()
===
reference
.
parent
)
{
this
.
_tree
.
reveal
(
reference
);
}
else
{
if
(
revealParent
)
{
...
...
src/vs/platform/list/browser/listService.ts
浏览文件 @
419d5bba
...
...
@@ -35,7 +35,7 @@ import { ObjectTree, IObjectTreeOptions } from 'vs/base/browser/ui/tree/objectTr
import
{
ITreeEvent
,
ITreeRenderer
,
IAsyncDataSource
}
from
'
vs/base/browser/ui/tree/tree
'
;
import
{
AsyncDataTree
,
IAsyncDataTreeOptions
}
from
'
vs/base/browser/ui/tree/asyncDataTree
'
;
export
type
ListWidget
=
List
<
any
>
|
PagedList
<
any
>
|
ITree
|
ObjectTree
<
any
,
any
>
|
AsyncDataTree
<
any
,
any
>
;
export
type
ListWidget
=
List
<
any
>
|
PagedList
<
any
>
|
ITree
|
ObjectTree
<
any
,
any
>
|
AsyncDataTree
<
any
,
any
,
any
>
;
export
const
IListService
=
createDecorator
<
IListService
>
(
'
listService
'
);
...
...
@@ -590,7 +590,7 @@ export class TreeResourceNavigator2<T, TFilterData> extends Disposable {
private
readonly
_openResource
:
Emitter
<
IOpenEvent
<
T
>>
=
new
Emitter
<
IOpenEvent
<
T
>>
();
readonly
openResource
:
Event
<
IOpenEvent
<
T
>>
=
this
.
_openResource
.
event
;
constructor
(
private
tree
:
WorkbenchObjectTree
<
T
,
TFilterData
>
|
WorkbenchAsyncDataTree
<
T
,
TFilterData
>
,
private
options
?:
IResourceResultsNavigationOptions
)
{
constructor
(
private
tree
:
WorkbenchObjectTree
<
T
,
TFilterData
>
|
WorkbenchAsyncDataTree
<
any
,
T
,
TFilterData
>
,
private
options
?:
IResourceResultsNavigationOptions
)
{
super
();
this
.
registerListeners
();
...
...
@@ -955,7 +955,7 @@ export class WorkbenchObjectTree<T extends NonNullable<any>, TFilterData = void>
}
}
export
class
WorkbenchAsyncDataTree
<
T
extends
NonNullable
<
any
>
,
TFilterData
=
void
>
extends
AsyncDataTree
<
T
,
TFilterData
>
{
export
class
WorkbenchAsyncDataTree
<
T
Input
,
T
,
TFilterData
=
void
>
extends
AsyncDataTree
<
TInput
,
T
,
TFilterData
>
{
readonly
contextKeyService
:
IContextKeyService
;
...
...
@@ -969,7 +969,7 @@ export class WorkbenchAsyncDataTree<T extends NonNullable<any>, TFilterData = vo
container
:
HTMLElement
,
delegate
:
IListVirtualDelegate
<
T
>
,
renderers
:
ITreeRenderer
<
any
/* TODO@joao */
,
TFilterData
,
any
>
[],
dataSource
:
IAsyncDataSource
<
T
>
,
dataSource
:
IAsyncDataSource
<
T
Input
,
T
>
,
options
:
IAsyncDataTreeOptions
<
T
,
TFilterData
>
,
@
IContextKeyService
contextKeyService
:
IContextKeyService
,
@
IListService
listService
:
IListService
,
...
...
src/vs/workbench/browser/viewlet.ts
浏览文件 @
419d5bba
...
...
@@ -186,7 +186,7 @@ export class CollapseAction extends Action {
// Collapse All action for the new tree
export
class
CollapseAction2
extends
Action
{
constructor
(
tree
:
AsyncDataTree
<
any
>
,
enabled
:
boolean
,
clazz
:
string
)
{
constructor
(
tree
:
AsyncDataTree
<
any
,
any
>
,
enabled
:
boolean
,
clazz
:
string
)
{
super
(
'
workbench.action.collapse
'
,
nls
.
localize
(
'
collapse
'
,
"
Collapse All
"
),
clazz
,
enabled
,
()
=>
{
tree
.
collapseAll
();
return
Promise
.
resolve
(
undefined
);
...
...
src/vs/workbench/parts/debug/browser/debugActions.ts
浏览文件 @
419d5bba
...
...
@@ -804,7 +804,7 @@ export class ReverseContinueAction extends AbstractDebugAction {
}
export
class
ReplCollapseAllAction
extends
CollapseAction2
{
constructor
(
tree
:
AsyncDataTree
<
any
>
,
private
toFocus
:
{
focus
():
void
;
})
{
constructor
(
tree
:
AsyncDataTree
<
any
,
any
>
,
private
toFocus
:
{
focus
():
void
;
})
{
super
(
tree
,
true
,
undefined
);
}
...
...
src/vs/workbench/parts/debug/browser/loadedScriptsView.ts
浏览文件 @
419d5bba
...
...
@@ -362,7 +362,7 @@ export class LoadedScriptsView extends ViewletPanel {
private
treeContainer
:
HTMLElement
;
private
loadedScriptsItemType
:
IContextKey
<
string
>
;
private
tree
:
WorkbenchAsyncDataTree
<
any
>
;
private
tree
:
WorkbenchAsyncDataTree
<
LoadedScriptsItem
,
LoadedScriptsItem
>
;
private
changeScheduler
:
RunOnceScheduler
;
private
treeNeedsRefreshOnVisible
:
boolean
;
private
filter
:
LoadedScriptsFilter
;
...
...
@@ -399,7 +399,7 @@ export class LoadedScriptsView extends ViewletPanel {
[
this
.
instantiationService
.
createInstance
(
LoadedScriptsRenderer
)
],
new
LoadedScriptsDataSource
(
root
),
new
LoadedScriptsDataSource
(),
{
identityProvider
:
{
getId
:
element
=>
element
.
getId
()
...
...
@@ -414,10 +414,12 @@ export class LoadedScriptsView extends ViewletPanel {
this
.
contextKeyService
,
this
.
listService
,
this
.
themeService
,
this
.
configurationService
,
this
.
keybindingService
);
this
.
tree
.
setInput
(
root
);
this
.
changeScheduler
=
new
RunOnceScheduler
(()
=>
{
this
.
treeNeedsRefreshOnVisible
=
false
;
if
(
this
.
tree
)
{
this
.
tree
.
refresh
(
null
);
this
.
tree
.
refresh
();
}
},
300
);
this
.
disposables
.
push
(
this
.
changeScheduler
);
...
...
@@ -535,19 +537,13 @@ class LoadedScriptsDelegate implements IListVirtualDelegate<LoadedScriptsItem> {
}
}
class
LoadedScriptsDataSource
implements
IAsyncDataSource
<
LoadedScriptsItem
>
{
constructor
(
private
root
:
LoadedScriptsItem
)
{
}
class
LoadedScriptsDataSource
implements
IAsyncDataSource
<
LoadedScriptsItem
,
LoadedScriptsItem
>
{
hasChildren
(
element
:
LoadedScriptsItem
|
null
):
boolean
{
return
element
===
null
||
element
.
hasChildren
();
hasChildren
(
element
:
LoadedScriptsItem
):
boolean
{
return
element
.
hasChildren
();
}
getChildren
(
element
:
LoadedScriptsItem
|
null
):
Promise
<
LoadedScriptsItem
[]
>
{
if
(
element
===
null
)
{
element
=
this
.
root
;
}
getChildren
(
element
:
LoadedScriptsItem
):
Promise
<
LoadedScriptsItem
[]
>
{
return
element
.
getChildren
();
}
}
...
...
src/vs/workbench/parts/debug/electron-browser/callStackView.ts
浏览文件 @
419d5bba
...
...
@@ -7,7 +7,7 @@ import * as nls from 'vs/nls';
import
{
RunOnceScheduler
,
ignoreErrors
}
from
'
vs/base/common/async
'
;
import
*
as
dom
from
'
vs/base/browser/dom
'
;
import
{
IViewletViewOptions
}
from
'
vs/workbench/browser/parts/views/viewsViewlet
'
;
import
{
IDebugService
,
State
,
IStackFrame
,
IDebugSession
,
IThread
,
CONTEXT_CALLSTACK_ITEM_TYPE
}
from
'
vs/workbench/parts/debug/common/debug
'
;
import
{
IDebugService
,
State
,
IStackFrame
,
IDebugSession
,
IThread
,
CONTEXT_CALLSTACK_ITEM_TYPE
,
IDebugModel
}
from
'
vs/workbench/parts/debug/common/debug
'
;
import
{
Thread
,
StackFrame
,
ThreadAndSessionIds
}
from
'
vs/workbench/parts/debug/common/debugModel
'
;
import
{
IContextMenuService
}
from
'
vs/platform/contextview/browser/contextView
'
;
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
...
...
@@ -45,7 +45,7 @@ export class CallStackView extends ViewletPanel {
private
ignoreFocusStackFrameEvent
:
boolean
;
private
callStackItemType
:
IContextKey
<
string
>
;
private
dataSource
:
CallStackDataSource
;
private
tree
:
WorkbenchAsyncDataTree
<
CallStackItem
>
;
private
tree
:
WorkbenchAsyncDataTree
<
IDebugModel
,
CallStackItem
>
;
private
contributedContextMenu
:
IMenu
;
constructor
(
...
...
@@ -84,7 +84,7 @@ export class CallStackView extends ViewletPanel {
this
.
needsRefresh
=
false
;
this
.
dataSource
.
deemphasizedStackFramesToShow
=
[];
this
.
tree
.
refresh
(
null
).
then
(()
=>
this
.
updateTreeSelection
());
this
.
tree
.
refresh
().
then
(()
=>
this
.
updateTreeSelection
());
},
50
);
}
...
...
@@ -101,7 +101,7 @@ export class CallStackView extends ViewletPanel {
dom
.
addClass
(
container
,
'
debug-call-stack
'
);
const
treeContainer
=
renderViewTree
(
container
);
this
.
dataSource
=
new
CallStackDataSource
(
this
.
debugService
);
this
.
dataSource
=
new
CallStackDataSource
();
this
.
tree
=
new
WorkbenchAsyncDataTree
(
treeContainer
,
new
CallStackDelegate
(),
[
new
SessionsRenderer
(),
new
ThreadsRenderer
(),
...
...
@@ -144,6 +144,9 @@ export class CallStackView extends ViewletPanel {
}
},
this
.
contextKeyService
,
this
.
listService
,
this
.
themeService
,
this
.
configurationService
,
this
.
keybindingService
);
// TODO@isidor this is a promise
this
.
tree
.
setInput
(
this
.
debugService
.
getModel
());
const
callstackNavigator
=
new
TreeResourceNavigator2
(
this
.
tree
);
this
.
disposables
.
push
(
callstackNavigator
);
this
.
disposables
.
push
(
callstackNavigator
.
openResource
(
e
=>
{
...
...
@@ -176,12 +179,12 @@ export class CallStackView extends ViewletPanel {
const
thread
=
session
&&
session
.
getThread
(
element
.
threadId
);
if
(
thread
)
{
(
<
Thread
>
thread
).
fetchCallStack
()
.
then
(()
=>
this
.
tree
.
refresh
(
null
));
.
then
(()
=>
this
.
tree
.
refresh
());
}
}
if
(
element
instanceof
Array
)
{
this
.
dataSource
.
deemphasizedStackFramesToShow
.
push
(...
element
);
this
.
tree
.
refresh
(
null
);
this
.
tree
.
refresh
();
}
}));
...
...
@@ -571,19 +574,20 @@ class CallStackDelegate implements IListVirtualDelegate<CallStackItem> {
}
}
class
CallStackDataSource
implements
IAsyncDataSource
<
CallStackItem
>
{
deemphasizedStackFramesToShow
:
IStackFrame
[];
function
isDebugModel
(
obj
:
any
):
obj
is
IDebugModel
{
return
typeof
obj
.
getSessions
===
'
function
'
;
}
constructor
(
private
debugService
:
IDebugService
)
{
}
class
CallStackDataSource
implements
IAsyncDataSource
<
IDebugModel
,
CallStackItem
>
{
deemphasizedStackFramesToShow
:
IStackFrame
[];
hasChildren
(
element
:
CallStackItem
|
null
):
boolean
{
return
element
===
null
||
element
instanceof
DebugSession
||
(
element
instanceof
Thread
&&
element
.
stopped
);
hasChildren
(
element
:
IDebugModel
|
CallStackItem
):
boolean
{
return
isDebugModel
(
element
)
||
element
instanceof
DebugSession
||
(
element
instanceof
Thread
&&
element
.
stopped
);
}
getChildren
(
element
:
CallStackItem
|
null
):
Promise
<
CallStackItem
[]
>
{
if
(
element
===
null
)
{
const
model
=
this
.
debugService
.
getModel
();
const
sessions
=
model
.
getSessions
();
getChildren
(
element
:
IDebugModel
|
CallStackItem
):
Promise
<
CallStackItem
[]
>
{
if
(
isDebugModel
(
element
))
{
const
sessions
=
element
.
getSessions
();
if
(
sessions
.
length
===
0
)
{
return
Promise
.
resolve
([]);
}
...
...
@@ -594,12 +598,11 @@ class CallStackDataSource implements IAsyncDataSource<CallStackItem> {
const
threads
=
sessions
[
0
].
getAllThreads
();
// Only show the threads in the call stack if there is more than 1 thread.
return
threads
.
length
===
1
?
this
.
getThreadChildren
(
<
Thread
>
threads
[
0
])
:
Promise
.
resolve
(
threads
);
}
if
(
element
instanceof
DebugSession
)
{
}
else
if
(
element
instanceof
DebugSession
)
{
return
Promise
.
resolve
(
element
.
getAllThreads
());
}
else
{
return
this
.
getThreadChildren
(
<
Thread
>
element
);
}
return
this
.
getThreadChildren
(
<
Thread
>
element
);
}
private
getThreadChildren
(
thread
:
Thread
):
Promise
<
Array
<
IStackFrame
|
string
|
ThreadAndSessionIds
>>
{
...
...
src/vs/workbench/parts/debug/electron-browser/debugHover.ts
浏览文件 @
419d5bba
...
...
@@ -45,7 +45,7 @@ export class DebugHoverWidget implements IContentWidget {
private
_isVisible
:
boolean
;
private
domNode
:
HTMLElement
;
private
tree
:
AsyncDataTree
<
IExpression
>
;
private
tree
:
AsyncDataTree
<
IExpression
,
IExpression
>
;
private
showAtPosition
:
Position
;
private
highlightDecorations
:
string
[];
private
complexValueContainer
:
HTMLElement
;
...
...
@@ -237,9 +237,8 @@ export class DebugHoverWidget implements IContentWidget {
this
.
valueContainer
.
hidden
=
true
;
this
.
complexValueContainer
.
hidden
=
false
;
this
.
dataSource
.
expression
=
expression
;
return
this
.
tree
.
refresh
(
null
).
then
(()
=>
{
return
this
.
tree
.
setInput
(
expression
).
then
(()
=>
{
this
.
complexValueTitle
.
textContent
=
expression
.
value
;
this
.
complexValueTitle
.
title
=
expression
.
value
;
this
.
layoutTreeAndContainer
();
...
...
@@ -291,19 +290,13 @@ class DebugHoverAccessibilityProvider implements IAccessibilityProvider<IExpress
}
}
class
DebugHoverDataSource
implements
IAsyncDataSource
<
IExpression
>
{
class
DebugHoverDataSource
implements
IAsyncDataSource
<
IExpression
,
IExpression
>
{
expression
:
IExpression
;
hasChildren
(
element
:
IExpression
|
null
):
boolean
{
return
element
===
null
||
element
.
hasChildren
;
hasChildren
(
element
:
IExpression
):
boolean
{
return
element
.
hasChildren
;
}
getChildren
(
element
:
IExpression
|
null
):
Promise
<
IExpression
[]
>
{
if
(
element
===
null
)
{
element
=
this
.
expression
;
}
getChildren
(
element
:
IExpression
):
Promise
<
IExpression
[]
>
{
return
element
.
getChildren
();
}
}
...
...
src/vs/workbench/parts/debug/electron-browser/repl.ts
浏览文件 @
419d5bba
...
...
@@ -81,7 +81,7 @@ interface IPrivateReplService {
clearRepl
():
void
;
}
function
revealLastElement
<
T
>
(
tree
:
WorkbenchAsyncDataTree
<
T
>
)
{
function
revealLastElement
(
tree
:
WorkbenchAsyncDataTree
<
any
,
any
>
)
{
tree
.
scrollTop
=
tree
.
scrollHeight
-
tree
.
renderHeight
;
}
...
...
@@ -95,7 +95,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
private
static
readonly
REPL_INPUT_MAX_HEIGHT
=
170
;
private
history
:
HistoryNavigator
<
string
>
;
private
tree
:
WorkbenchAsyncDataTree
<
IReplElement
>
;
private
tree
:
WorkbenchAsyncDataTree
<
null
,
IReplElement
>
;
private
dataSource
:
ReplDataSource
;
private
replDelegate
:
ReplDelegate
;
private
container
:
HTMLElement
;
...
...
@@ -213,7 +213,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
if
(
this
.
tree
&&
this
.
dataSource
.
input
!==
session
)
{
this
.
dataSource
.
input
=
session
;
this
.
tree
.
refresh
(
null
).
then
(()
=>
revealLastElement
(
this
.
tree
));
this
.
tree
.
refresh
().
then
(()
=>
revealLastElement
(
this
.
tree
));
}
}
...
...
@@ -331,7 +331,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
private
get
refreshScheduler
():
RunOnceScheduler
{
return
new
RunOnceScheduler
(()
=>
{
const
lastElementVisible
=
this
.
tree
.
scrollTop
+
this
.
tree
.
renderHeight
>=
this
.
tree
.
scrollHeight
;
this
.
tree
.
refresh
(
null
).
then
(()
=>
{
this
.
tree
.
refresh
().
then
(()
=>
{
if
(
lastElementVisible
)
{
// Only scroll if we were scrolled all the way down before tree refreshed #10486
revealLastElement
(
this
.
tree
);
...
...
@@ -363,6 +363,8 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
keyboardNavigationLabelProvider
:
{
getKeyboardNavigationLabel
:
e
=>
e
}
},
this
.
contextKeyService
,
this
.
listService
,
this
.
themeService
,
this
.
configurationService
,
this
.
keybindingService
);
this
.
tree
.
setInput
(
null
);
this
.
toDispose
.
push
(
this
.
tree
.
onContextMenu
(
e
=>
this
.
onContextMenu
(
e
)));
// Make sure to select the session if debugging is already active
this
.
selectSession
();
...
...
@@ -750,7 +752,7 @@ class ReplDelegate implements IListVirtualDelegate<IReplElement> {
}
class
ReplDataSource
implements
IAsyncDataSource
<
IReplElement
>
{
class
ReplDataSource
implements
IAsyncDataSource
<
null
,
IReplElement
>
{
input
:
IDebugSession
;
hasChildren
(
element
:
IReplElement
|
null
):
boolean
{
...
...
src/vs/workbench/parts/debug/electron-browser/variablesView.ts
浏览文件 @
419d5bba
...
...
@@ -8,7 +8,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import
*
as
dom
from
'
vs/base/browser/dom
'
;
import
{
CollapseAction2
}
from
'
vs/workbench/browser/viewlet
'
;
import
{
IViewletViewOptions
}
from
'
vs/workbench/browser/parts/views/viewsViewlet
'
;
import
{
IDebugService
,
IExpression
,
IScope
,
CONTEXT_VARIABLES_FOCUSED
}
from
'
vs/workbench/parts/debug/common/debug
'
;
import
{
IDebugService
,
IExpression
,
IScope
,
CONTEXT_VARIABLES_FOCUSED
,
IViewModel
}
from
'
vs/workbench/parts/debug/common/debug
'
;
import
{
Variable
,
Scope
}
from
'
vs/workbench/parts/debug/common/debugModel
'
;
import
{
IContextMenuService
}
from
'
vs/platform/contextview/browser/contextView
'
;
import
{
IKeybindingService
}
from
'
vs/platform/keybinding/common/keybinding
'
;
...
...
@@ -37,7 +37,7 @@ export class VariablesView extends ViewletPanel {
private
onFocusStackFrameScheduler
:
RunOnceScheduler
;
private
needsRefresh
:
boolean
;
private
tree
:
WorkbenchAsyncDataTree
<
IExpression
|
IScope
>
;
private
tree
:
WorkbenchAsyncDataTree
<
I
ViewModel
,
I
Expression
|
IScope
>
;
constructor
(
options
:
IViewletViewOptions
,
...
...
@@ -55,7 +55,7 @@ export class VariablesView extends ViewletPanel {
// Use scheduler to prevent unnecessary flashing
this
.
onFocusStackFrameScheduler
=
new
RunOnceScheduler
(()
=>
{
this
.
needsRefresh
=
false
;
this
.
tree
.
refresh
(
null
).
then
(()
=>
{
this
.
tree
.
refresh
().
then
(()
=>
{
const
stackFrame
=
this
.
debugService
.
getViewModel
().
focusedStackFrame
;
if
(
stackFrame
)
{
stackFrame
.
getScopes
().
then
(
scopes
=>
{
...
...
@@ -75,18 +75,21 @@ export class VariablesView extends ViewletPanel {
this
.
tree
=
new
WorkbenchAsyncDataTree
(
treeContainer
,
new
VariablesDelegate
(),
[
this
.
instantiationService
.
createInstance
(
VariablesRenderer
),
new
ScopesRenderer
()],
new
VariablesDataSource
(
this
.
debugService
),
{
new
VariablesDataSource
(),
{
ariaLabel
:
nls
.
localize
(
'
variablesAriaTreeLabel
'
,
"
Debug Variables
"
),
accessibilityProvider
:
new
VariablesAccessibilityProvider
(),
identityProvider
:
{
getId
:
element
=>
element
.
getId
()
},
keyboardNavigationLabelProvider
:
{
getKeyboardNavigationLabel
:
e
=>
e
}
},
this
.
contextKeyService
,
this
.
listService
,
this
.
themeService
,
this
.
configurationService
,
this
.
keybindingService
);
// TODO@isidor this is a promise
this
.
tree
.
setInput
(
this
.
debugService
.
getViewModel
());
CONTEXT_VARIABLES_FOCUSED
.
bindTo
(
this
.
contextKeyService
.
createScoped
(
treeContainer
));
const
collapseAction
=
new
CollapseAction2
(
this
.
tree
,
true
,
'
explorer-action collapse-explorer
'
);
this
.
toolbar
.
setActions
([
collapseAction
])();
this
.
tree
.
refresh
(
null
);
this
.
tree
.
refresh
();
this
.
disposables
.
push
(
this
.
debugService
.
getViewModel
().
onDidFocusStackFrame
(
sf
=>
{
if
(
!
this
.
isVisible
()
||
!
this
.
isExpanded
())
{
...
...
@@ -99,7 +102,7 @@ export class VariablesView extends ViewletPanel {
const
timeout
=
sf
.
explicit
?
0
:
undefined
;
this
.
onFocusStackFrameScheduler
.
schedule
(
timeout
);
}));
this
.
disposables
.
push
(
variableSetEmitter
.
event
(()
=>
this
.
tree
.
refresh
(
null
)));
this
.
disposables
.
push
(
variableSetEmitter
.
event
(()
=>
this
.
tree
.
refresh
()));
this
.
disposables
.
push
(
this
.
tree
.
onMouseDblClick
(
e
=>
this
.
onMouseDblClick
(
e
)));
this
.
disposables
.
push
(
this
.
tree
.
onContextMenu
(
e
=>
this
.
onContextMenu
(
e
)));
}
...
...
@@ -149,21 +152,23 @@ export class VariablesView extends ViewletPanel {
}
}
export
class
VariablesDataSource
implements
IAsyncDataSource
<
IExpression
|
IScope
>
{
function
isViewModel
(
obj
:
any
):
obj
is
IViewModel
{
return
typeof
obj
.
getSelectedExpression
===
'
function
'
;
}
constructor
(
private
debugService
:
IDebugService
)
{
}
export
class
VariablesDataSource
implements
IAsyncDataSource
<
IViewModel
,
IExpression
|
IScope
>
{
hasChildren
(
element
:
I
Expression
|
IScope
|
null
):
boolean
{
if
(
element
===
null
||
element
instanceof
Scope
)
{
hasChildren
(
element
:
I
ViewModel
|
IExpression
|
IScope
):
boolean
{
if
(
isViewModel
(
element
)
||
element
instanceof
Scope
)
{
return
true
;
}
return
element
.
hasChildren
;
}
getChildren
(
element
:
I
Expression
|
IScope
|
null
):
Promise
<
Array
<
IExpression
|
IScope
>
>
{
if
(
element
===
null
)
{
const
stackFrame
=
this
.
debugService
.
getViewModel
()
.
focusedStackFrame
;
getChildren
(
element
:
I
ViewModel
|
IExpression
|
IScope
):
Promise
<
(
IExpression
|
IScope
)[]
>
{
if
(
isViewModel
(
element
)
)
{
const
stackFrame
=
element
.
focusedStackFrame
;
return
stackFrame
?
stackFrame
.
getScopes
()
:
Promise
.
resolve
([]);
}
...
...
src/vs/workbench/parts/debug/electron-browser/watchExpressionsView.ts
浏览文件 @
419d5bba
...
...
@@ -34,7 +34,7 @@ export class WatchExpressionsView extends ViewletPanel {
private
onWatchExpressionsUpdatedScheduler
:
RunOnceScheduler
;
private
needsRefresh
:
boolean
;
private
tree
:
WorkbenchAsyncDataTree
<
IExpression
>
;
private
tree
:
WorkbenchAsyncDataTree
<
I
DebugService
,
I
Expression
>
;
constructor
(
options
:
IViewletViewOptions
,
...
...
@@ -51,7 +51,7 @@ export class WatchExpressionsView extends ViewletPanel {
this
.
onWatchExpressionsUpdatedScheduler
=
new
RunOnceScheduler
(()
=>
{
this
.
needsRefresh
=
false
;
this
.
tree
.
refresh
(
null
);
this
.
tree
.
refresh
();
},
50
);
}
...
...
@@ -63,14 +63,15 @@ export class WatchExpressionsView extends ViewletPanel {
const
expressionsRenderer
=
this
.
instantiationService
.
createInstance
(
WatchExpressionsRenderer
);
this
.
disposables
.
push
(
expressionsRenderer
);
this
.
tree
=
new
WorkbenchAsyncDataTree
(
treeContainer
,
new
WatchExpressionsDelegate
(),
[
expressionsRenderer
,
this
.
instantiationService
.
createInstance
(
VariablesRenderer
)],
new
WatchExpressionsDataSource
(
this
.
debugService
),
{
new
WatchExpressionsDataSource
(),
{
ariaLabel
:
nls
.
localize
({
comment
:
[
'
Debug is a noun in this context, not a verb.
'
],
key
:
'
watchAriaTreeLabel
'
},
"
Debug Watch Expressions
"
),
accessibilityProvider
:
new
WatchExpressionsAccessibilityProvider
(),
identityProvider
:
{
getId
:
element
=>
element
.
getId
()
},
keyboardNavigationLabelProvider
:
{
getKeyboardNavigationLabel
:
e
=>
e
}
},
this
.
contextKeyService
,
this
.
listService
,
this
.
themeService
,
this
.
configurationService
,
this
.
keybindingService
);
this
.
tree
.
refresh
(
null
);
// TODO@isidor this is a promise
this
.
tree
.
setInput
(
this
.
debugService
);
const
addWatchExpressionAction
=
new
AddWatchExpressionAction
(
AddWatchExpressionAction
.
ID
,
AddWatchExpressionAction
.
LABEL
,
this
.
debugService
,
this
.
keybindingService
);
const
collapseAction
=
new
CollapseAction2
(
this
.
tree
,
true
,
'
explorer-action collapse-explorer
'
);
...
...
@@ -83,7 +84,7 @@ export class WatchExpressionsView extends ViewletPanel {
if
(
!
this
.
isExpanded
()
||
!
this
.
isVisible
())
{
this
.
needsRefresh
=
true
;
}
else
{
this
.
tree
.
refresh
(
null
);
this
.
tree
.
refresh
();
}
}));
this
.
disposables
.
push
(
this
.
debugService
.
getViewModel
().
onDidFocusStackFrame
(()
=>
{
...
...
@@ -96,7 +97,7 @@ export class WatchExpressionsView extends ViewletPanel {
this
.
onWatchExpressionsUpdatedScheduler
.
schedule
();
}
}));
this
.
disposables
.
push
(
variableSetEmitter
.
event
(()
=>
this
.
tree
.
refresh
(
null
)));
this
.
disposables
.
push
(
variableSetEmitter
.
event
(()
=>
this
.
tree
.
refresh
()));
}
layoutBody
(
size
:
number
):
void
{
...
...
@@ -186,22 +187,21 @@ class WatchExpressionsDelegate implements IListVirtualDelegate<IExpression> {
}
}
class
WatchExpressionsDataSource
implements
IAsyncDataSource
<
IExpression
>
{
function
isDebugService
(
element
:
any
):
element
is
IDebugService
{
return
typeof
element
.
getConfigurationManager
===
'
function
'
;
}
constructor
(
private
debugService
:
IDebugService
)
{
}
class
WatchExpressionsDataSource
implements
IAsyncDataSource
<
IDebugService
,
IExpression
>
{
hasChildren
(
element
:
IExpression
|
null
):
boolean
{
if
(
element
===
null
)
{
return
true
;
}
return
element
.
hasChildren
;
return
isDebugService
(
element
)
||
element
.
hasChildren
;
}
getChildren
(
element
:
IExpression
|
null
):
Promise
<
Array
<
IExpression
>>
{
if
(
element
===
null
)
{
const
watchExpressions
=
this
.
debugService
.
getModel
().
getWatchExpressions
();
const
viewModel
=
this
.
debugService
.
getViewModel
();
getChildren
(
element
:
IDebugService
|
IExpression
):
Promise
<
Array
<
IExpression
>>
{
if
(
isDebugService
(
element
))
{
const
debugService
=
element
as
IDebugService
;
const
watchExpressions
=
debugService
.
getModel
().
getWatchExpressions
();
const
viewModel
=
debugService
.
getViewModel
();
return
Promise
.
all
(
watchExpressions
.
map
(
we
=>
!!
we
.
name
?
we
.
evaluate
(
viewModel
.
focusedSession
,
viewModel
.
focusedStackFrame
,
'
watch
'
).
then
(()
=>
we
)
:
Promise
.
resolve
(
we
)));
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录