Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
90d2232f
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,体验更适合开发者的 AI 搜索 >>
提交
90d2232f
编写于
5月 09, 2018
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
async loading, keep state when editors change
上级
894e3a74
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
160 addition
and
106 deletion
+160
-106
src/vs/workbench/parts/outline/electron-browser/outlineModel.ts
.../workbench/parts/outline/electron-browser/outlineModel.ts
+60
-13
src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts
.../workbench/parts/outline/electron-browser/outlinePanel.ts
+83
-79
src/vs/workbench/parts/outline/electron-browser/outlineTree.ts
...s/workbench/parts/outline/electron-browser/outlineTree.ts
+17
-14
未找到文件。
src/vs/workbench/parts/outline/electron-browser/outlineModel.ts
浏览文件 @
90d2232f
...
...
@@ -12,29 +12,38 @@ import { fuzzyScore } from '../../../../base/common/filters';
import
{
IPosition
}
from
'
vs/editor/common/core/position
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
values
}
from
'
vs/base/common/map
'
;
import
URI
from
'
vs/base/common/uri
'
;
export
function
getOutline
(
model
:
ITextModel
):
TPromise
<
OutlineItemGroup
[]
>
{
let
outlines
=
new
Array
<
OutlineItemGroup
>
();
let
promises
=
DocumentSymbolProviderRegistry
.
ordered
(
model
).
map
((
provider
,
i
)
=>
{
export
function
getOutline
(
model
:
ITextModel
):
TPromise
<
OutlineItemGroup
>
[]
{
return
DocumentSymbolProviderRegistry
.
ordered
(
model
).
map
((
provider
,
i
)
=>
{
let
source
=
`provider
${
i
}
`
;
return
asWinJsPromise
(
token
=>
provider
.
provideDocumentSymbols
(
model
,
token
)).
then
(
result
=>
{
let
source
=
`provider
${
i
}
`
;
let
items
=
result
.
map
(
info
=>
asOutlineItem
(
info
,
undefined
));
outlines
.
push
(
new
OutlineItemGroup
(
source
,
items
));
let
items
=
result
.
map
(
info
=>
asOutlineItem
(
info
,
source
));
return
new
OutlineItemGroup
(
source
,
items
);
},
err
=>
{
//
//todo@joh capture error in group
return
new
OutlineItemGroup
(
source
,
[]);
});
});
return
TPromise
.
join
(
promises
).
then
(()
=>
outlines
);
}
function
asOutlineItem
(
info
:
SymbolInformation
,
parent
:
OutlineItem
):
OutlineItem
{
function
asOutlineItem
(
info
:
SymbolInformation
,
parentOrExtensionId
:
OutlineItem
|
string
):
OutlineItem
{
// complex id-computation which contains the origin/extension,
// the parent path, and some dedupe logic when names collide
let
parent
:
OutlineItem
;
let
id
=
info
.
name
;
if
(
parent
)
{
id
=
parent
.
id
+
info
.
name
;
for
(
let
i
=
1
;
parent
.
children
.
has
(
id
);
i
++
)
{
id
=
parent
.
id
+
info
.
name
+
i
;
if
(
typeof
parentOrExtensionId
===
'
string
'
)
{
id
=
parentOrExtensionId
+
id
;
}
else
if
(
parentOrExtensionId
)
{
parent
=
parentOrExtensionId
;
id
=
parentOrExtensionId
.
id
+
info
.
name
;
for
(
let
i
=
1
;
parentOrExtensionId
.
children
.
has
(
id
);
i
++
)
{
id
=
parentOrExtensionId
.
id
+
info
.
name
+
i
;
}
}
// build item and recurse
let
res
=
new
OutlineItem
(
id
,
info
,
parent
);
if
(
info
.
children
)
{
for
(
const
child
of
info
.
children
)
{
...
...
@@ -138,3 +147,41 @@ export class OutlineItemGroup {
return
undefined
;
}
}
export
class
OutlineModel
{
constructor
(
readonly
uri
:
URI
,
private
_requests
:
TPromise
<
OutlineItemGroup
>
[]
)
{
//
}
dispose
():
void
{
this
.
_cancelRequests
();
}
private
_cancelRequests
()
{
for
(
const
req
of
this
.
_requests
)
{
req
.
cancel
();
}
}
all
():
TPromise
<
OutlineItemGroup
>
[]
{
return
this
.
_requests
;
}
selected
():
TPromise
<
OutlineItemGroup
>
{
// todo@joh allow to 'select' results from different providers
return
this
.
_requests
[
0
];
}
merge
(
other
:
OutlineModel
):
boolean
{
if
(
this
.
uri
.
toString
()
!==
other
.
uri
.
toString
())
{
return
false
;
}
this
.
_cancelRequests
();
this
.
_requests
=
other
.
_requests
;
return
true
;
}
}
src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts
浏览文件 @
90d2232f
...
...
@@ -30,9 +30,10 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import
{
IViewOptions
,
ViewsViewletPanel
}
from
'
vs/workbench/browser/parts/views/viewsViewlet
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IEditorGroupService
}
from
'
vs/workbench/services/group/common/groupService
'
;
import
{
OutlineItem
,
OutlineItemGroup
,
getOutline
}
from
'
./outlineModel
'
;
import
{
OutlineItem
,
getOutline
,
OutlineModel
}
from
'
./outlineModel
'
;
import
{
OutlineDataSource
,
OutlineItemComparator
,
OutlineItemCompareType
,
OutlineItemFilter
,
OutlineRenderer
,
OutlineTreeState
}
from
'
./outlineTree
'
;
import
{
KeyCode
}
from
'
../../../../base/common/keyCodes
'
;
import
{
LRUCache
}
from
'
../../../../base/common/map
'
;
class
ActiveEditorOracle
{
...
...
@@ -93,7 +94,8 @@ export class OutlinePanel extends ViewsViewletPanel {
private
_tree
:
Tree
;
private
_treeFilter
:
OutlineItemFilter
;
private
_treeComparator
:
OutlineItemComparator
;
private
_followCursor
:
boolean
=
true
;
private
_treeStates
=
new
LRUCache
<
string
,
OutlineTreeState
>
(
10
);
private
_followCursor
=
true
;
constructor
(
options
:
IViewOptions
,
...
...
@@ -173,94 +175,96 @@ export class OutlinePanel extends ViewsViewletPanel {
}
}
private
_onEditor
(
editor
:
ICodeEditor
):
void
{
private
async
_onEditor
(
editor
:
ICodeEditor
):
TPromise
<
void
>
{
dispose
(
this
.
_editorDisposables
);
this
.
_editorDisposables
=
new
Array
();
this
.
_input
.
disable
();
if
(
!
editor
)
{
//
return
;
//
todo@joh show empty message
return
undefined
;
}
// todo@joh show pending...
const
promise
=
getOutline
(
editor
.
getModel
()).
then
(
outline
=>
{
let
model
=
<
OutlineItemGroup
>
this
.
_tree
.
getInput
();
let
[
first
]
=
outline
;
if
(
!
first
)
{
return
;
// todo@joh
let
textModel
=
editor
.
getModel
();
let
oldModel
=
<
OutlineModel
>
this
.
_tree
.
getInput
();
let
model
=
new
OutlineModel
(
textModel
.
uri
,
getOutline
(
textModel
));
if
(
oldModel
&&
oldModel
.
merge
(
model
))
{
model
=
oldModel
;
this
.
_tree
.
refresh
(
undefined
,
true
);
}
else
{
// persist state
if
(
oldModel
)
{
let
state
=
OutlineTreeState
.
capture
(
this
.
_tree
);
this
.
_treeStates
.
set
(
oldModel
.
uri
.
toString
(),
state
);
}
await
this
.
_tree
.
setInput
(
model
);
let
state
=
this
.
_treeStates
.
get
(
model
.
uri
.
toString
());
OutlineTreeState
.
restore
(
this
.
_tree
,
state
);
}
if
(
model
instanceof
OutlineItemGroup
&&
first
.
source
===
model
.
source
)
{
model
.
children
.
splice
(
0
,
model
.
children
.
length
,
...
first
.
children
);
this
.
_tree
.
refresh
(
undefined
,
true
);
}
else
{
this
.
_tree
.
setInput
(
first
);
// wait for the actual model to work with...
let
itemGroup
=
await
model
.
selected
();
this
.
_input
.
enable
();
// feature: filter on type
// on type -> update filters
// on first type -> capture tree state
// on erase -> restore captured tree state
let
beforePatternState
:
OutlineTreeState
;
this
.
_editorDisposables
.
push
(
this
.
_input
.
onDidChange
(
async
pattern
=>
{
if
(
!
beforePatternState
)
{
beforePatternState
=
OutlineTreeState
.
capture
(
this
.
_tree
);
}
let
item
=
itemGroup
.
updateMatches
(
pattern
);
await
this
.
_tree
.
refresh
(
undefined
,
true
);
if
(
item
)
{
await
this
.
_tree
.
reveal
(
item
);
this
.
_tree
.
setFocus
(
item
,
this
);
this
.
_tree
.
setSelection
([
item
],
this
);
this
.
_tree
.
expandAll
(
undefined
/*all*/
);
}
this
.
_editorDisposables
.
push
(
editor
.
onDidChangeCursorSelection
(
async
e
=>
{
if
(
!
this
.
_followCursor
||
e
.
reason
!==
CursorChangeReason
.
Explicit
)
{
return
;
}
let
item
=
model
.
getItemEnclosingPosition
({
lineNumber
:
e
.
selection
.
selectionStartLineNumber
,
column
:
e
.
selection
.
selectionStartColumn
});
if
(
item
)
{
await
this
.
_tree
.
reveal
(
item
);
this
.
_tree
.
setFocus
(
item
,
this
);
this
.
_tree
.
setSelection
([
item
],
this
);
}
else
{
this
.
_tree
.
setSelection
([],
this
);
}
}));
this
.
_input
.
enable
();
let
beforePatternState
:
OutlineTreeState
;
this
.
_editorDisposables
.
push
(
this
.
_input
.
onDidChange
(
async
pattern
=>
{
if
(
!
beforePatternState
)
{
beforePatternState
=
OutlineTreeState
.
capture
(
this
.
_tree
);
}
let
item
=
model
.
updateMatches
(
pattern
);
await
this
.
_tree
.
refresh
(
undefined
,
true
);
if
(
item
)
{
await
this
.
_tree
.
reveal
(
item
);
this
.
_tree
.
setFocus
(
item
,
this
);
this
.
_tree
.
setSelection
([
item
],
this
);
this
.
_tree
.
expandAll
(
undefined
/*all*/
);
}
if
(
!
pattern
&&
beforePatternState
)
{
await
OutlineTreeState
.
restore
(
this
.
_tree
,
beforePatternState
);
beforePatternState
=
undefined
;
}
}));
this
.
_editorDisposables
.
push
(
this
.
_tree
.
onDidChangeSelection
(
e
=>
{
if
(
e
.
payload
===
this
)
{
return
;
}
let
[
first
]
=
e
.
selection
;
if
(
first
instanceof
OutlineItem
)
{
let
{
range
}
=
first
.
symbol
.
location
;
editor
.
revealRangeInCenterIfOutsideViewport
(
range
,
ScrollType
.
Smooth
);
editor
.
setSelection
(
Range
.
collapseToStart
(
range
));
// editor.focus();
}
}));
},
err
=>
{
//todo@joh have an error screen
console
.
error
(
err
);
});
if
(
!
pattern
&&
beforePatternState
)
{
await
OutlineTreeState
.
restore
(
this
.
_tree
,
beforePatternState
);
beforePatternState
=
undefined
;
}
}));
this
.
_editorDisposables
.
push
({
dispose
()
{
promise
.
cancel
();
// feature: reveal outline selection in editor
// on change -> reveal/select defining range
this
.
_editorDisposables
.
push
(
this
.
_tree
.
onDidChangeSelection
(
e
=>
{
if
(
e
.
payload
===
this
)
{
return
;
}
});
let
[
first
]
=
e
.
selection
;
if
(
first
instanceof
OutlineItem
)
{
let
{
range
}
=
first
.
symbol
.
location
;
editor
.
revealRangeInCenterIfOutsideViewport
(
range
,
ScrollType
.
Smooth
);
editor
.
setSelection
(
Range
.
collapseToStart
(
range
));
// editor.focus();
}
}));
// feature: reveal editor selection in outline
this
.
_editorDisposables
.
push
(
editor
.
onDidChangeCursorSelection
(
async
e
=>
{
if
(
!
this
.
_followCursor
||
e
.
reason
!==
CursorChangeReason
.
Explicit
)
{
return
;
}
let
item
=
itemGroup
.
getItemEnclosingPosition
({
lineNumber
:
e
.
selection
.
selectionStartLineNumber
,
column
:
e
.
selection
.
selectionStartColumn
});
if
(
item
)
{
await
this
.
_tree
.
reveal
(
item
);
this
.
_tree
.
setFocus
(
item
,
this
);
this
.
_tree
.
setSelection
([
item
],
this
);
}
else
{
this
.
_tree
.
setSelection
([],
this
);
}
}));
}
}
src/vs/workbench/parts/outline/electron-browser/outlineTree.ts
浏览文件 @
90d2232f
...
...
@@ -10,7 +10,7 @@ import * as dom from 'vs/base/browser/dom';
import
{
symbolKindToCssClass
}
from
'
vs/editor/common/modes
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
IDataSource
,
IRenderer
,
ITree
,
ISorter
,
IFilter
}
from
'
vs/base/parts/tree/browser/tree
'
;
import
{
OutlineItem
Group
,
OutlineItem
}
from
'
./outlineModel
'
;
import
{
OutlineItem
,
OutlineModel
}
from
'
./outlineModel
'
;
import
{
HighlightedLabel
}
from
'
../../../../base/browser/ui/highlightedlabel/highlightedLabel
'
;
import
{
createMatches
}
from
'
../../../../base/common/filters
'
;
import
{
values
}
from
'
vs/base/common/map
'
;
...
...
@@ -56,27 +56,29 @@ export class OutlineDataSource implements IDataSource {
}
}
hasChildren
(
tree
:
ITree
,
element
:
Outline
ItemGroup
|
OutlineItem
):
boolean
{
if
(
element
instanceof
Outline
ItemGroup
)
{
return
element
.
children
.
length
>
0
;
hasChildren
(
tree
:
ITree
,
element
:
Outline
Model
|
OutlineItem
):
boolean
{
if
(
element
instanceof
Outline
Model
)
{
return
element
.
all
()
.
length
>
0
;
}
else
{
let
res
=
element
.
children
.
size
>
0
;
if
(
res
)
{
if
(
element
.
children
.
size
===
0
)
{
return
false
;
}
else
{
let
res
:
boolean
;
element
.
children
.
forEach
(
child
=>
res
=
res
||
Boolean
(
child
.
matches
));
return
res
;
}
return
res
;
}
}
async
getChildren
(
tree
:
ITree
,
element
:
Outline
ItemGroup
|
OutlineItem
):
TPromise
<
any
,
any
>
{
if
(
element
instanceof
Outline
ItemGroup
)
{
return
element
.
children
;
async
getChildren
(
tree
:
ITree
,
element
:
Outline
Model
|
OutlineItem
):
TPromise
<
OutlineItem
[]
>
{
if
(
element
instanceof
Outline
Model
)
{
return
(
await
element
.
selected
())
.
children
;
}
else
{
return
values
(
element
.
children
);
}
}
async
getParent
(
tree
:
ITree
,
element
:
OutlineItem
Group
|
OutlineItem
):
TPromise
<
any
,
any
>
{
async
getParent
(
tree
:
ITree
,
element
:
OutlineItem
|
any
):
TPromise
<
OutlineItem
>
{
return
element
instanceof
OutlineItem
?
element
.
parent
:
undefined
;
}
...
...
@@ -137,13 +139,14 @@ export class OutlineTreeState {
}
static
async
restore
(
tree
:
ITree
,
state
:
OutlineTreeState
):
TPromise
<
void
>
{
let
input
=
<
OutlineItemGroup
>
tree
.
getInput
();
if
(
!
(
input
instanceof
OutlineItemGroup
))
{
let
model
=
<
OutlineModel
>
tree
.
getInput
();
if
(
!
state
||
!
(
model
instanceof
OutlineModel
))
{
return
TPromise
.
as
(
undefined
);
}
let
group
=
await
model
.
selected
();
let
items
:
OutlineItem
[]
=
[];
for
(
const
id
of
state
.
expanded
)
{
let
item
=
input
.
getItemById
(
id
);
let
item
=
group
.
getItemById
(
id
);
if
(
item
)
{
items
.
push
(
item
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录