Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
3eabca14
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 搜索 >>
提交
3eabca14
编写于
12月 19, 2018
作者:
I
isidor
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
explorer: simplify explorer view, it no longer resolves stats
上级
c0dfd8bd
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
65 addition
and
200 deletion
+65
-200
src/vs/workbench/parts/files/common/files.ts
src/vs/workbench/parts/files/common/files.ts
+2
-2
src/vs/workbench/parts/files/electron-browser/explorerService.ts
...workbench/parts/files/electron-browser/explorerService.ts
+7
-6
src/vs/workbench/parts/files/electron-browser/fileActions.ts
src/vs/workbench/parts/files/electron-browser/fileActions.ts
+1
-10
src/vs/workbench/parts/files/electron-browser/fileCommands.ts
...vs/workbench/parts/files/electron-browser/fileCommands.ts
+2
-1
src/vs/workbench/parts/files/electron-browser/views/explorerView.ts
...kbench/parts/files/electron-browser/views/explorerView.ts
+47
-168
src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts
...ench/parts/files/electron-browser/views/explorerViewer.ts
+6
-13
未找到文件。
src/vs/workbench/parts/files/common/files.ts
浏览文件 @
3eabca14
...
...
@@ -41,7 +41,7 @@ export interface IEditableData {
export
interface
IExplorerService
{
_serviceBrand
:
any
;
readonly
roots
:
ExplorerItem
[];
readonly
onDidChangeItem
:
Event
<
ExplorerItem
>
;
readonly
onDidChangeItem
:
Event
<
ExplorerItem
|
undefined
>
;
readonly
onDidChangeEditable
:
Event
<
ExplorerItem
>
;
readonly
onDidSelectItem
:
Event
<
{
item
:
ExplorerItem
,
reveal
:
boolean
}
>
;
...
...
@@ -53,7 +53,7 @@ export interface IExplorerService {
* Selects and reveal the file element provided by the given resource if its found in the explorer. Will try to
* resolve the path from the disk in case the explorer is not yet expanded to the file yet.
*/
select
(
resource
:
URI
,
reveal
?:
boolean
):
void
;
select
(
resource
:
URI
,
reveal
?:
boolean
):
Promise
<
void
>
;
}
export
const
IExplorerService
=
createDecorator
<
IExplorerService
>
(
'
explorerService
'
);
...
...
src/vs/workbench/parts/files/electron-browser/explorerService.ts
浏览文件 @
3eabca14
...
...
@@ -30,7 +30,7 @@ export class ExplorerService implements IExplorerService {
private
static
readonly
EXPLORER_FILE_CHANGES_REACT_DELAY
=
500
;
// delay in ms to react to file changes to give our internal events a chance to react first
private
_onDidChangeItem
=
new
Emitter
<
ExplorerItem
>
();
private
_onDidChangeItem
=
new
Emitter
<
ExplorerItem
|
undefined
>
();
private
_onDidChangeEditable
=
new
Emitter
<
ExplorerItem
>
();
private
_onDidSelectItem
=
new
Emitter
<
{
item
:
ExplorerItem
,
reveal
:
boolean
}
>
();
private
disposables
:
IDisposable
[]
=
[];
...
...
@@ -49,7 +49,7 @@ export class ExplorerService implements IExplorerService {
return
this
.
model
.
roots
;
}
get
onDidChangeItem
():
Event
<
ExplorerItem
>
{
get
onDidChangeItem
():
Event
<
ExplorerItem
|
undefined
>
{
return
this
.
_onDidChangeItem
.
event
;
}
...
...
@@ -79,6 +79,7 @@ export class ExplorerService implements IExplorerService {
this
.
disposables
.
push
(
this
.
fileService
.
onAfterOperation
(
e
=>
this
.
onFileOperation
(
e
)));
this
.
disposables
.
push
(
this
.
fileService
.
onFileChanges
(
e
=>
this
.
onFileChanges
(
e
)));
this
.
disposables
.
push
(
this
.
configurationService
.
onDidChangeConfiguration
(
e
=>
this
.
onConfigurationUpdated
(
this
.
configurationService
.
getValue
<
IFilesConfiguration
>
())));
this
.
disposables
.
push
(
this
.
fileService
.
onDidChangeFileSystemProviderRegistrations
(()
=>
this
.
_onDidChangeItem
.
fire
()));
return
model
;
}
...
...
@@ -96,18 +97,18 @@ export class ExplorerService implements IExplorerService {
return
this
.
editableStats
.
get
(
stat
);
}
select
(
resource
:
URI
,
reveal
?:
boolean
):
void
{
select
(
resource
:
URI
,
reveal
?:
boolean
):
Promise
<
void
>
{
const
fileStat
=
this
.
findClosest
(
resource
);
if
(
fileStat
)
{
this
.
_onDidSelectItem
.
fire
({
item
:
fileStat
,
reveal
});
return
;
return
Promise
.
resolve
(
void
0
)
;
}
// Stat needs to be resolved first and then revealed
const
options
:
IResolveFileOptions
=
{
resolveTo
:
[
resource
]
};
const
workspaceFolder
=
this
.
contextService
.
getWorkspaceFolder
(
resource
);
const
rootUri
=
workspaceFolder
?
workspaceFolder
.
uri
:
this
.
roots
[
0
].
resource
;
this
.
fileService
.
resolveFile
(
rootUri
,
options
).
then
(
stat
=>
{
return
this
.
fileService
.
resolveFile
(
rootUri
,
options
).
then
(
stat
=>
{
// Convert to model
const
root
=
this
.
roots
.
filter
(
r
=>
r
.
resource
.
toString
()
===
rootUri
.
toString
()).
pop
();
...
...
@@ -120,7 +121,6 @@ export class ExplorerService implements IExplorerService {
},
e
=>
{
this
.
notificationService
.
error
(
e
);
});
}
private
onConfigurationUpdated
(
configuration
:
IFilesConfiguration
,
event
?:
IConfigurationChangeEvent
):
void
{
const
configSortOrder
=
configuration
&&
configuration
.
explorer
&&
configuration
.
explorer
.
sortOrder
||
'
default
'
;
if
(
this
.
sortOrder
!==
configSortOrder
)
{
...
...
@@ -130,6 +130,7 @@ export class ExplorerService implements IExplorerService {
}
// File events
private
onFileOperation
(
e
:
FileOperationEvent
):
void
{
// Add
if
(
e
.
operation
===
FileOperation
.
CREATE
||
e
.
operation
===
FileOperation
.
COPY
)
{
...
...
src/vs/workbench/parts/files/electron-browser/fileActions.ts
浏览文件 @
3eabca14
...
...
@@ -20,7 +20,6 @@ import { VIEWLET_ID, IExplorerService } from 'vs/workbench/parts/files/common/fi
import
{
ITextFileService
,
ITextFileOperationResult
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
IFileService
,
IFileStat
,
AutoSaveConfiguration
}
from
'
vs/platform/files/common/files
'
;
import
{
toResource
,
IUntitledResourceInput
}
from
'
vs/workbench/common/editor
'
;
import
{
ExplorerView
}
from
'
vs/workbench/parts/files/electron-browser/views/explorerView
'
;
import
{
ExplorerViewlet
}
from
'
vs/workbench/parts/files/electron-browser/explorerViewlet
'
;
import
{
IUntitledEditorService
}
from
'
vs/workbench/services/untitled/common/untitledEditorService
'
;
import
{
IQuickOpenService
}
from
'
vs/platform/quickOpen/common/quickOpen
'
;
...
...
@@ -985,14 +984,6 @@ export class GlobalCompareResourcesAction extends Action {
}
}
// Refresh Explorer Viewer
export
class
RefreshViewExplorerAction
extends
Action
{
constructor
(
explorerView
:
ExplorerView
,
clazz
:
string
)
{
super
(
'
workbench.files.action.refreshFilesExplorer
'
,
nls
.
localize
(
'
refresh
'
,
"
Refresh
"
),
clazz
,
true
,
(
context
:
any
)
=>
explorerView
.
refresh
());
}
}
export
class
ToggleAutoSaveAction
extends
Action
{
public
static
readonly
ID
=
'
workbench.action.toggleAutoSave
'
;
public
static
readonly
LABEL
=
nls
.
localize
(
'
toggleAutoSave
'
,
"
Toggle Auto Save
"
);
...
...
@@ -1215,7 +1206,7 @@ export class RefreshExplorerView extends Action {
label
:
string
,
@
IViewletService
private
viewletService
:
IViewletService
)
{
super
(
id
,
label
);
super
(
id
,
label
,
'
explorer-action refresh-explorer
'
);
}
public
run
():
Promise
<
any
>
{
...
...
src/vs/workbench/parts/files/electron-browser/fileCommands.ts
浏览文件 @
3eabca14
...
...
@@ -39,6 +39,7 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import
{
IEditorService
,
SIDE_GROUP
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IEditorGroupsService
}
from
'
vs/workbench/services/group/common/editorGroupsService
'
;
import
{
ILabelService
}
from
'
vs/platform/label/common/label
'
;
import
{
onUnexpectedError
}
from
'
vs/base/common/errors
'
;
// Commands
...
...
@@ -472,7 +473,7 @@ CommandsRegistry.registerCommand({
const
explorerView
=
viewlet
.
getExplorerView
();
if
(
explorerView
)
{
explorerView
.
setExpanded
(
true
);
explorerService
.
select
(
uri
,
true
);
explorerService
.
select
(
uri
,
true
)
.
then
(
undefined
,
onUnexpectedError
)
;
}
}
else
{
const
openEditorsView
=
viewlet
.
getOpenEditorsView
();
...
...
src/vs/workbench/parts/files/electron-browser/views/explorerView.ts
浏览文件 @
3eabca14
...
...
@@ -7,13 +7,11 @@ import * as nls from 'vs/nls';
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
*
as
perf
from
'
vs/base/common/performance
'
;
import
{
ThrottledDelayer
,
sequence
,
ignoreErrors
}
from
'
vs/base/common/async
'
;
import
*
as
paths
from
'
vs/base/common/paths
'
;
import
*
as
resources
from
'
vs/base/common/resources
'
;
import
{
Action
,
IAction
}
from
'
vs/base/common/actions
'
;
import
{
memoize
}
from
'
vs/base/common/decorators
'
;
import
{
IFilesConfiguration
,
ExplorerFolderContext
,
FilesExplorerFocusedContext
,
ExplorerFocusedContext
,
ExplorerRootContext
,
ExplorerResourceReadonlyContext
,
IExplorerService
}
from
'
vs/workbench/parts/files/common/files
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
RefreshViewExplorerAction
,
NewFolderAction
,
NewFileAction
,
FileCopiedContext
}
from
'
vs/workbench/parts/files/electron-browser/fileActions
'
;
import
{
NewFolderAction
,
NewFileAction
,
FileCopiedContext
,
RefreshExplorerView
}
from
'
vs/workbench/parts/files/electron-browser/fileActions
'
;
import
{
toResource
}
from
'
vs/workbench/common/editor
'
;
import
{
DiffEditorInput
}
from
'
vs/workbench/common/editor/diffEditorInput
'
;
import
*
as
DOM
from
'
vs/base/browser/dom
'
;
...
...
@@ -45,14 +43,14 @@ import { fillInContextMenuActions } from 'vs/platform/actions/browser/menuItemAc
import
{
IClipboardService
}
from
'
vs/platform/clipboard/common/clipboardService
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
ExplorerItem
,
NewStatPlaceholder
}
from
'
vs/workbench/parts/files/common/explorerModel
'
;
import
{
onUnexpectedError
}
from
'
vs/base/common/errors
'
;
export
class
ExplorerView
extends
ViewletPanel
{
static
readonly
ID
:
string
=
'
workbench.explorer.fileView
'
;
private
static
readonly
EXPLORER_FILE_CHANGES_REFRESH_DELAY
=
100
;
// delay in ms to refresh the explorer from disk file changes
private
tree
:
WorkbenchAsyncDataTree
<
null
,
ExplorerItem
>
;
private
tree
:
WorkbenchAsyncDataTree
<
ExplorerItem
|
ExplorerItem
[]
,
ExplorerItem
>
;
private
filter
:
FilesFilter
;
private
isCreated
:
boolean
;
private
explorerRefreshDelayer
:
ThrottledDelayer
<
void
>
;
...
...
@@ -61,7 +59,8 @@ export class ExplorerView extends ViewletPanel {
private
readonlyContext
:
IContextKey
<
boolean
>
;
private
rootContext
:
IContextKey
<
boolean
>
;
private
shouldRefresh
:
boolean
;
// Refresh is needed on the initial explorer open
private
shouldRefresh
=
true
;
private
dragHandler
:
DelayedDragHandler
;
private
decorationProvider
:
ExplorerDecorationsProvider
;
private
autoReveal
=
false
;
...
...
@@ -74,7 +73,6 @@ export class ExplorerView extends ViewletPanel {
@
IWorkspaceContextService
private
contextService
:
IWorkspaceContextService
,
@
IProgressService
private
progressService
:
IProgressService
,
@
IEditorService
private
editorService
:
IEditorService
,
@
IFileService
private
fileService
:
IFileService
,
@
IPartService
private
partService
:
IPartService
,
@
IKeybindingService
keybindingService
:
IKeybindingService
,
@
IContextKeyService
private
contextKeyService
:
IContextKeyService
,
...
...
@@ -159,17 +157,11 @@ export class ExplorerView extends ViewletPanel {
const
configuration
=
this
.
configurationService
.
getValue
<
IFilesConfiguration
>
();
this
.
onConfigurationUpdated
(
configuration
);
//
Load and Fill Viewer
this
.
d
oRefresh
().
then
(()
=>
{
//
When the explorer viewer is loaded, listen to changes to the editor input
this
.
d
isposables
.
push
(
this
.
editorService
.
onDidActiveEditorChange
(()
=>
this
.
revealActiveFile
()));
// When the explorer viewer is loaded, listen to changes to the editor input
this
.
disposables
.
push
(
this
.
editorService
.
onDidActiveEditorChange
(()
=>
this
.
revealActiveFile
()));
// Also handle configuration updates
this
.
disposables
.
push
(
this
.
configurationService
.
onDidChangeConfiguration
(
e
=>
this
.
onConfigurationUpdated
(
this
.
configurationService
.
getValue
<
IFilesConfiguration
>
(),
e
)));
this
.
revealActiveFile
();
});
// Also handle configuration updates
this
.
disposables
.
push
(
this
.
configurationService
.
onDidChangeConfiguration
(
e
=>
this
.
onConfigurationUpdated
(
this
.
configurationService
.
getValue
<
IFilesConfiguration
>
(),
e
)));
}
renderBody
(
container
:
HTMLElement
):
void
{
...
...
@@ -180,16 +172,16 @@ export class ExplorerView extends ViewletPanel {
this
.
toolbar
.
setActions
(
this
.
getActions
(),
this
.
getSecondaryActions
())();
}
this
.
disposables
.
push
(
this
.
contextService
.
onDidChangeWorkspaceFolders
(
e
=>
this
.
refreshFromEvent
(
e
.
added
)));
this
.
disposables
.
push
(
this
.
contextService
.
onDidChangeWorkbenchState
(()
=>
this
.
refreshFromEvent
()));
this
.
disposables
.
push
(
this
.
fileService
.
onDidChangeFileSystemProviderRegistrations
(()
=>
this
.
refreshFromEvent
()));
this
.
disposables
.
push
(
this
.
contextService
.
onDidChangeWorkspaceFolders
(
e
=>
this
.
setTreeInput
(
e
.
added
)));
this
.
disposables
.
push
(
this
.
contextService
.
onDidChangeWorkbenchState
(()
=>
this
.
setTreeInput
()));
this
.
disposables
.
push
(
this
.
labelService
.
onDidRegisterFormatter
(()
=>
{
this
.
_onDidChangeTitleArea
.
fire
();
this
.
refreshFromEvent
();
}));
this
.
disposables
.
push
(
this
.
explorerService
.
onDidChangeItem
(
e
=>
this
.
refreshFromEvent
(
e
)));
this
.
disposables
.
push
(
this
.
explorerService
.
onDidChangeEditable
(
e
=>
this
.
refresh
(
e
.
parent
)));
this
.
disposables
.
push
(
this
.
explorerService
.
onDidSelectItem
(
e
=>
this
.
onSelectItem
(
e
.
item
,
e
.
reveal
)));
// TODO@Isidor plug in other explorer service events
}
getActions
():
IAction
[]
{
...
...
@@ -197,7 +189,7 @@ export class ExplorerView extends ViewletPanel {
actions
.
push
(
this
.
instantiationService
.
createInstance
(
NewFileAction
,
null
));
actions
.
push
(
this
.
instantiationService
.
createInstance
(
NewFolderAction
,
null
));
actions
.
push
(
this
.
instantiationService
.
createInstance
(
Refresh
ViewExplorerAction
,
this
,
'
explorer-action refresh-explorer
'
));
actions
.
push
(
this
.
instantiationService
.
createInstance
(
Refresh
ExplorerView
,
RefreshExplorerView
.
ID
,
RefreshExplorerView
.
LABEL
));
actions
.
push
(
this
.
instantiationService
.
createInstance
(
CollapseAction2
,
this
.
tree
,
true
,
'
explorer-action collapse-explorer
'
));
return
actions
;
...
...
@@ -219,7 +211,7 @@ export class ExplorerView extends ViewletPanel {
if
(
this
.
isVisible
()
&&
!
this
.
isDisposed
&&
this
.
contextService
.
isInsideWorkspace
(
activeFile
))
{
const
selection
=
this
.
hasSingleSelection
(
activeFile
);
if
(
!
selection
)
{
this
.
explorerService
.
select
(
activeFile
);
this
.
explorerService
.
select
(
activeFile
)
.
then
(
undefined
,
onUnexpectedError
)
;
}
clearSelection
=
false
;
...
...
@@ -270,50 +262,12 @@ export class ExplorerView extends ViewletPanel {
setVisible
(
visible
:
boolean
):
void
{
super
.
setVisible
(
visible
);
// Show
if
(
visible
)
{
DOM
.
show
(
this
.
tree
.
getHTMLElement
());
// If a refresh was requested and we are now visible, run it
let
refreshPromise
=
Promise
.
resolve
(
null
);
if
(
this
.
shouldRefresh
)
{
refreshPromise
=
this
.
doRefresh
()
;
this
.
s
houldRefresh
=
false
;
// Reset flag
this
.
shouldRefresh
=
false
;
this
.
s
etTreeInput
().
then
(
undefined
,
onUnexpectedError
);
}
if
(
!
this
.
autoReveal
)
{
return
;
// do not react to setVisible call if autoReveal === false
}
// Always select the current navigated file in explorer if input is file editor input
// unless autoReveal is set to false
const
activeFile
=
this
.
getActiveFile
();
if
(
activeFile
)
{
refreshPromise
.
then
(()
=>
{
this
.
explorerService
.
select
(
activeFile
);
});
return
;
}
// Return now if the workbench has not yet been restored - in this case the workbench takes care of restoring last used editors
if
(
!
this
.
partService
.
isRestored
())
{
return
;
}
// Otherwise restore last used file: By lastActiveFileResource
const
focusedElements
=
this
.
tree
.
getFocus
();
if
(
focusedElements
&&
focusedElements
.
length
)
{
this
.
editorService
.
openEditor
({
resource
:
focusedElements
[
0
].
resource
,
options
:
{
revealIfVisible
:
true
}
});
return
;
}
// Otherwise restore last used file: By Explorer selection
refreshPromise
.
then
(()
=>
{
this
.
openFocusedElement
();
});
}
else
{
// make sure the tree goes out of the tabindex world by hiding it
DOM
.
hide
(
this
.
tree
.
getHTMLElement
());
}
}
...
...
@@ -361,7 +315,6 @@ export class ExplorerView extends ViewletPanel {
FilesExplorerFocusedContext
.
bindTo
(
this
.
tree
.
contextKeyService
);
ExplorerFocusedContext
.
bindTo
(
this
.
tree
.
contextKeyService
);
// Update resource context based on focused element
this
.
disposables
.
push
(
this
.
tree
.
onDidChangeFocus
(
e
=>
{
const
stat
=
e
.
elements
&&
e
.
elements
.
length
?
e
.
elements
[
0
]
:
undefined
;
...
...
@@ -433,20 +386,14 @@ export class ExplorerView extends ViewletPanel {
// Refresh viewer as needed if this originates from a config event
if
(
event
&&
needsRefresh
)
{
this
.
doR
efresh
();
this
.
r
efresh
();
}
}
private
refreshFromEvent
(
newRoots
:
IWorkspaceFolder
[]
=
[]
):
void
{
private
refreshFromEvent
(
explorerItem
?:
ExplorerItem
):
void
{
if
(
this
.
isVisible
()
&&
!
this
.
isDisposed
)
{
this
.
explorerRefreshDelayer
.
trigger
(()
=>
{
return
this
.
doRefresh
().
then
(()
=>
{
if
(
newRoots
.
length
===
1
)
{
return
this
.
tree
.
reveal
(
this
.
explorerService
.
findClosest
(
newRoots
[
0
].
uri
),
0.5
);
}
return
undefined
;
});
return
this
.
refresh
(
explorerItem
);
});
}
else
{
this
.
shouldRefresh
=
true
;
...
...
@@ -486,118 +433,50 @@ export class ExplorerView extends ViewletPanel {
/**
* Refresh the contents of the explorer to get up to date data from the disk about the file structure.
*/
refresh
():
Promise
<
void
>
{
refresh
(
item
?:
ExplorerItem
):
Promise
<
void
>
{
if
(
!
this
.
tree
)
{
return
Promise
.
resolve
(
void
0
);
}
const
toRefresh
=
item
||
this
.
tree
.
getInput
();
// Focus
this
.
tree
.
domFocus
();
return
this
.
tree
.
refresh
(
toRefresh
,
true
);
}
// Find resource to focus from active editor input if set
let
resourceToFocus
:
URI
;
if
(
this
.
autoReveal
)
{
resourceToFocus
=
this
.
getActiveFile
();
if
(
!
resourceToFocus
)
{
const
selection
=
this
.
tree
.
getSelection
();
if
(
selection
&&
selection
.
length
===
1
)
{
resourceToFocus
=
selection
[
0
].
resource
;
}
}
private
setTreeInput
(
newRoots
?:
IWorkspaceFolder
[]):
Promise
<
void
>
{
if
(
!
this
.
isVisible
())
{
this
.
shouldRefresh
=
true
;
return
Promise
.
resolve
(
void
0
);
}
return
this
.
doRefresh
().
then
(()
=>
{
if
(
resourceToFocus
)
{
return
this
.
explorerService
.
select
(
resourceToFocus
,
true
);
}
perf
.
mark
(
'
willResolveExplorer
'
);
const
roots
=
this
.
explorerService
.
roots
;
let
input
:
ExplorerItem
|
ExplorerItem
[]
=
roots
[
0
];
if
(
this
.
contextService
.
getWorkbenchState
()
!==
WorkbenchState
.
FOLDER
||
roots
[
0
].
isError
)
{
// Display roots only when multi folder workspace
input
=
roots
;
}
return
Promise
.
resolve
(
void
0
);
});
}
const
promise
=
this
.
tree
.
setInput
(
input
).
then
(()
=>
{
let
expandPromise
=
Promise
.
resolve
(
void
0
);
if
(
newRoots
&&
newRoots
.
length
)
{
expandPromise
=
Promise
.
all
(
newRoots
.
map
(
workspaceFolder
=>
this
.
tree
.
expand
(
this
.
explorerService
.
findClosest
(
workspaceFolder
.
uri
))));
}
private
doRefresh
():
Promise
<
any
>
{
const
targetsToResolve
=
this
.
explorerService
.
roots
.
map
(
root
=>
({
root
,
resource
:
root
.
resource
,
options
:
{
resolveTo
:
[]
}
}));
// First time refresh: Receive target through active editor input or selection and also include settings from previous session
if
(
!
this
.
isCreated
)
{
const
activeFile
=
this
.
getActiveFile
();
if
(
activeFile
)
{
const
workspaceFolder
=
this
.
contextService
.
getWorkspaceFolder
(
activeFile
);
if
(
workspaceFolder
)
{
const
found
=
targetsToResolve
.
filter
(
t
=>
t
.
root
.
resource
.
toString
()
===
workspaceFolder
.
uri
.
toString
()).
pop
();
found
.
options
.
resolveTo
.
push
(
activeFile
);
// Find resource to focus from active editor input if set
if
(
this
.
autoReveal
)
{
const
resourceToFocus
=
this
.
getActiveFile
();
if
(
resourceToFocus
)
{
return
expandPromise
.
then
(()
=>
this
.
explorerService
.
select
(
resourceToFocus
,
true
));
}
}
}
// Subsequent refresh: Receive targets through expanded folders in tree
else
{
targetsToResolve
.
forEach
(
t
=>
{
this
.
getResolvedDirectories
(
t
.
root
,
t
.
options
.
resolveTo
);
});
}
return
expandPromise
;
}).
then
(()
=>
perf
.
mark
(
'
didResolveExplorer
'
));
const
promise
=
this
.
resolveRoots
(
targetsToResolve
).
then
(
result
=>
{
this
.
isCreated
=
true
;
this
.
decorationProvider
.
changed
(
targetsToResolve
.
map
(
t
=>
t
.
root
.
resource
));
return
result
;
});
this
.
progressService
.
showWhile
(
promise
,
this
.
partService
.
isRestored
()
?
800
:
1200
/* less ugly initial startup */
);
return
promise
;
}
private
resolveRoots
(
targetsToResolve
:
{
root
:
ExplorerItem
,
resource
:
URI
,
options
:
{
resolveTo
:
any
[]
}
}[]):
Promise
<
any
>
{
if
(
!
this
.
isCreated
)
{
perf
.
mark
(
'
willResolveExplorer
'
);
}
const
errorRoot
=
(
resource
:
URI
,
root
:
ExplorerItem
)
=>
{
return
ExplorerItem
.
create
({
resource
:
resource
,
name
:
paths
.
basename
(
resource
.
fsPath
),
mtime
:
0
,
etag
:
undefined
,
isDirectory
:
true
},
root
,
undefined
,
true
);
};
if
(
targetsToResolve
.
every
(
t
=>
t
.
root
.
resource
.
scheme
===
'
file
'
))
{
// All the roots are local, resolve them in parallel
return
this
.
fileService
.
resolveFiles
(
targetsToResolve
).
then
(
results
=>
{
// Convert to model
const
modelStats
=
results
.
map
((
result
,
index
)
=>
{
if
(
result
.
success
&&
result
.
stat
.
isDirectory
)
{
return
ExplorerItem
.
create
(
result
.
stat
,
targetsToResolve
[
index
].
root
,
targetsToResolve
[
index
].
options
.
resolveTo
);
}
return
errorRoot
(
targetsToResolve
[
index
].
resource
,
targetsToResolve
[
index
].
root
);
});
// Subsequent refresh: Merge stat into our local model and refresh tree
modelStats
.
forEach
((
modelStat
,
index
)
=>
{
if
(
index
<
this
.
explorerService
.
roots
.
length
)
{
ExplorerItem
.
mergeLocalWithDisk
(
modelStat
,
this
.
explorerService
.
roots
[
index
]);
}
});
return
this
.
tree
.
setInput
(
null
);
});
}
// There is a remote root, resolve the roots sequantally
return
Promise
.
all
(
targetsToResolve
.
map
((
target
,
index
)
=>
this
.
fileService
.
resolveFile
(
target
.
resource
,
target
.
options
)
.
then
(
result
=>
result
.
isDirectory
?
ExplorerItem
.
create
(
result
,
target
.
root
,
target
.
options
.
resolveTo
)
:
errorRoot
(
target
.
resource
,
target
.
root
),
()
=>
errorRoot
(
target
.
resource
,
target
.
root
))
.
then
(
modelStat
=>
{
// Subsequent refresh: Merge stat into our local model and refresh tree
if
(
index
<
this
.
explorerService
.
roots
.
length
)
{
ExplorerItem
.
mergeLocalWithDisk
(
modelStat
,
this
.
explorerService
.
roots
[
index
]);
}
return
this
.
tree
.
setInput
(
null
);
})));
}
/**
* Given a stat, fills an array of path that make all folders below the stat that are resolved directories.
*/
...
...
src/vs/workbench/parts/files/electron-browser/views/explorerViewer.ts
浏览文件 @
3eabca14
...
...
@@ -47,29 +47,22 @@ export class ExplorerDelegate implements IListVirtualDelegate<ExplorerItem> {
}
}
export
class
ExplorerDataSource
implements
IAsyncDataSource
<
null
,
ExplorerItem
>
{
export
class
ExplorerDataSource
implements
IAsyncDataSource
<
ExplorerItem
|
ExplorerItem
[]
,
ExplorerItem
>
{
constructor
(
@
IExplorerService
private
explorerService
:
IExplorerService
,
@
IProgressService
private
progressService
:
IProgressService
,
@
INotificationService
private
notificationService
:
INotificationService
,
@
IFileService
private
fileService
:
IFileService
,
@
IPartService
private
partService
:
IPartService
,
@
IWorkspaceContextService
private
contextService
:
IWorkspaceContextService
)
{
}
hasChildren
(
element
:
ExplorerItem
|
null
):
boolean
{
return
element
===
null
||
element
.
isDirectory
;
hasChildren
(
element
:
ExplorerItem
|
ExplorerItem
[]
):
boolean
{
return
Array
.
isArray
(
element
)
||
element
.
isDirectory
;
}
getChildren
(
element
:
ExplorerItem
|
null
):
Promise
<
ExplorerItem
[]
>
{
if
(
element
===
null
)
{
const
roots
=
this
.
explorerService
.
roots
;
if
(
this
.
contextService
.
getWorkbenchState
()
!==
WorkbenchState
.
FOLDER
||
roots
[
0
].
isError
)
{
// Display roots only when multi folder workspace
return
Promise
.
resolve
(
roots
);
}
element
=
roots
[
0
];
getChildren
(
element
:
ExplorerItem
|
ExplorerItem
[]):
Promise
<
ExplorerItem
[]
>
{
if
(
Array
.
isArray
(
element
))
{
return
Promise
.
resolve
(
element
);
}
// Return early if stat is already resolved
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录