Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
4f33f591
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,发现更多精彩内容 >>
提交
4f33f591
编写于
6月 20, 2017
作者:
I
Isidor Nikolic
提交者:
GitHub
6月 20, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #29030 from Microsoft/isidorn/explorerModel
Isidorn/explorer model
上级
7cb99c87
8b6f9e64
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
242 addition
and
151 deletion
+242
-151
src/vs/platform/files/common/files.ts
src/vs/platform/files/common/files.ts
+5
-0
src/vs/workbench/parts/files/browser/fileActions.contribution.ts
...workbench/parts/files/browser/fileActions.contribution.ts
+1
-1
src/vs/workbench/parts/files/browser/fileActions.ts
src/vs/workbench/parts/files/browser/fileActions.ts
+1
-1
src/vs/workbench/parts/files/browser/fileCommands.ts
src/vs/workbench/parts/files/browser/fileCommands.ts
+1
-1
src/vs/workbench/parts/files/browser/views/explorerView.ts
src/vs/workbench/parts/files/browser/views/explorerView.ts
+124
-110
src/vs/workbench/parts/files/browser/views/explorerViewer.ts
src/vs/workbench/parts/files/browser/views/explorerViewer.ts
+36
-18
src/vs/workbench/parts/files/browser/views/openEditorsView.ts
...vs/workbench/parts/files/browser/views/openEditorsView.ts
+1
-1
src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts
.../workbench/parts/files/browser/views/openEditorsViewer.ts
+1
-1
src/vs/workbench/parts/files/common/explorerModel.ts
src/vs/workbench/parts/files/common/explorerModel.ts
+52
-10
src/vs/workbench/parts/files/common/files.ts
src/vs/workbench/parts/files/common/files.ts
+1
-1
src/vs/workbench/parts/files/test/browser/explorerModel.test.ts
.../workbench/parts/files/test/browser/explorerModel.test.ts
+6
-6
src/vs/workbench/services/configuration/node/configuration.ts
...vs/workbench/services/configuration/node/configuration.ts
+1
-1
src/vs/workbench/services/files/electron-browser/fileService.ts
.../workbench/services/files/electron-browser/fileService.ts
+4
-0
src/vs/workbench/services/files/node/fileService.ts
src/vs/workbench/services/files/node/fileService.ts
+4
-0
src/vs/workbench/test/workbenchTestServices.ts
src/vs/workbench/test/workbenchTestServices.ts
+4
-0
未找到文件。
src/vs/platform/files/common/files.ts
浏览文件 @
4f33f591
...
...
@@ -43,6 +43,11 @@ export interface IFileService {
*/
resolveFile
(
resource
:
URI
,
options
?:
IResolveFileOptions
):
TPromise
<
IFileStat
>
;
/**
* Same as resolveFile but supports resolving mulitple resources in parallel.
*/
resolveFiles
(
toResolve
:
{
resource
:
URI
,
options
?:
IResolveFileOptions
}[]):
TPromise
<
IFileStat
[]
>
;
/**
*Finds out if a file identified by the resource exists.
*/
...
...
src/vs/workbench/parts/files/browser/fileActions.contribution.ts
浏览文件 @
4f33f591
...
...
@@ -17,7 +17,7 @@ import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/wor
import
{
IInstantiationService
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
IWorkspaceContextService
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
IKeybindingService
}
from
'
vs/platform/keybinding/common/keybinding
'
;
import
{
FileStat
}
from
'
vs/workbench/parts/files/common/explorer
View
Model
'
;
import
{
FileStat
}
from
'
vs/workbench/parts/files/common/explorerModel
'
;
import
{
KeyMod
,
KeyChord
,
KeyCode
}
from
'
vs/base/common/keyCodes
'
;
import
{
OpenFolderAction
,
OpenFileFolderAction
}
from
'
vs/workbench/browser/actions/fileActions
'
;
import
{
copyFocusedFilesExplorerViewItem
,
revealInOSFocusedFilesExplorerItem
,
openFocusedExplorerItemSideBySideCommand
,
copyPathOfFocusedExplorerItem
,
copyPathCommand
,
revealInExplorerCommand
,
revealInOSCommand
,
openFolderPickerCommand
,
openWindowCommand
,
openFileInNewWindowCommand
,
deleteFocusedFilesExplorerViewItemCommand
,
moveFocusedFilesExplorerViewItemToTrashCommand
,
renameFocusedFilesExplorerViewItemCommand
}
from
'
vs/workbench/parts/files/browser/fileCommands
'
;
...
...
src/vs/workbench/parts/files/browser/fileActions.ts
浏览文件 @
4f33f591
...
...
@@ -27,7 +27,7 @@ import labels = require('vs/base/common/labels');
import
{
ITextFileService
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
IFileService
,
IFileStat
}
from
'
vs/platform/files/common/files
'
;
import
{
toResource
,
IEditorIdentifier
,
EditorInput
}
from
'
vs/workbench/common/editor
'
;
import
{
FileStat
,
NewStatPlaceholder
}
from
'
vs/workbench/parts/files/common/explorer
View
Model
'
;
import
{
FileStat
,
NewStatPlaceholder
}
from
'
vs/workbench/parts/files/common/explorerModel
'
;
import
{
ExplorerView
}
from
'
vs/workbench/parts/files/browser/views/explorerView
'
;
import
{
ExplorerViewlet
}
from
'
vs/workbench/parts/files/browser/explorerViewlet
'
;
import
{
IUntitledEditorService
}
from
'
vs/workbench/services/untitled/common/untitledEditorService
'
;
...
...
src/vs/workbench/parts/files/browser/fileCommands.ts
浏览文件 @
4f33f591
...
...
@@ -18,7 +18,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import
{
IWorkspaceContextService
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
ExplorerViewlet
}
from
'
vs/workbench/parts/files/browser/explorerViewlet
'
;
import
{
VIEWLET_ID
,
explorerItemToFileResource
}
from
'
vs/workbench/parts/files/common/files
'
;
import
{
FileStat
,
OpenEditor
}
from
'
vs/workbench/parts/files/common/explorer
View
Model
'
;
import
{
FileStat
,
OpenEditor
}
from
'
vs/workbench/parts/files/common/explorerModel
'
;
import
errors
=
require
(
'
vs/base/common/errors
'
);
import
{
ITree
}
from
'
vs/base/parts/tree/browser/tree
'
;
import
{
IClipboardService
}
from
'
vs/platform/clipboard/common/clipboardService
'
;
...
...
src/vs/workbench/parts/files/browser/views/explorerView.ts
浏览文件 @
4f33f591
...
...
@@ -14,6 +14,7 @@ import labels = require('vs/base/common/labels');
import
paths
=
require
(
'
vs/base/common/paths
'
);
import
{
Action
,
IAction
}
from
'
vs/base/common/actions
'
;
import
{
prepareActions
}
from
'
vs/workbench/browser/actions
'
;
import
{
memoize
}
from
'
vs/base/common/decorators
'
;
import
{
ITree
}
from
'
vs/base/parts/tree/browser/tree
'
;
import
{
Tree
}
from
'
vs/base/parts/tree/browser/treeImpl
'
;
import
{
IFilesConfiguration
,
ExplorerFolderContext
,
FilesExplorerFocussedContext
,
ExplorerFocussedContext
}
from
'
vs/workbench/parts/files/common/files
'
;
...
...
@@ -26,7 +27,7 @@ import { IEditorGroupService } from 'vs/workbench/services/group/common/groupSer
import
*
as
DOM
from
'
vs/base/browser/dom
'
;
import
{
CollapseAction
}
from
'
vs/workbench/browser/viewlet
'
;
import
{
CollapsibleView
,
IViewletViewOptions
}
from
'
vs/workbench/parts/views/browser/views
'
;
import
{
FileStat
}
from
'
vs/workbench/parts/files/common/explorerView
Model
'
;
import
{
FileStat
,
Model
}
from
'
vs/workbench/parts/files/common/explorer
Model
'
;
import
{
IListService
}
from
'
vs/platform/list/browser/listService
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IPartService
}
from
'
vs/workbench/services/part/common/partService
'
;
...
...
@@ -119,7 +120,12 @@ export class ExplorerView extends CollapsibleView {
public
renderHeader
(
container
:
HTMLElement
):
void
{
const
titleDiv
=
$
(
'
div.title
'
).
appendTo
(
container
);
$
(
'
span
'
).
text
(
this
.
name
).
title
(
labels
.
getPathLabel
(
this
.
contextService
.
getWorkspace
().
resource
.
fsPath
,
void
0
,
this
.
environmentService
)).
appendTo
(
titleDiv
);
const
setHeader
=
()
=>
{
const
title
=
this
.
contextService
.
getWorkspace2
().
roots
.
map
(
root
=>
labels
.
getPathLabel
(
root
.
fsPath
,
void
0
,
this
.
environmentService
)).
join
();
$
(
'
span
'
).
text
(
this
.
name
).
title
(
title
).
appendTo
(
titleDiv
);
};
this
.
toDispose
.
push
(
this
.
contextService
.
onDidChangeWorkspaceRoots
(()
=>
setHeader
()));
setHeader
();
super
.
renderHeader
(
container
);
}
...
...
@@ -140,6 +146,7 @@ export class ExplorerView extends CollapsibleView {
};
this
.
toDispose
.
push
(
this
.
themeService
.
onDidFileIconThemeChange
(
onFileIconThemeChange
));
this
.
toDispose
.
push
(
this
.
contextService
.
onDidChangeWorkspaceRoots
(()
=>
this
.
refreshFromEvent
()));
onFileIconThemeChange
(
this
.
themeService
.
getFileIconTheme
());
}
...
...
@@ -300,7 +307,7 @@ export class ExplorerView extends CollapsibleView {
lastActiveFileResource
=
URI
.
parse
(
this
.
settings
[
ExplorerView
.
MEMENTO_LAST_ACTIVE_FILE_RESOURCE
]);
}
if
(
lastActiveFileResource
&&
this
.
root
&&
this
.
root
.
find
(
lastActiveFileResource
))
{
if
(
lastActiveFileResource
&&
this
.
isCreated
&&
this
.
model
.
findFirst
(
lastActiveFileResource
))
{
this
.
editorService
.
openEditor
({
resource
:
lastActiveFileResource
,
options
:
{
revealIfVisible
:
true
}
}).
done
(
null
,
errors
.
onUnexpectedError
);
return
refreshPromise
;
...
...
@@ -334,8 +341,13 @@ export class ExplorerView extends CollapsibleView {
return
toResource
(
input
,
{
supportSideBySide
:
true
,
filter
:
'
file
'
});
}
private
get
root
():
FileStat
{
return
this
.
explorerViewer
?
(
<
FileStat
>
this
.
explorerViewer
.
getInput
())
:
null
;
private
get
isCreated
():
boolean
{
return
!!
(
this
.
explorerViewer
&&
this
.
explorerViewer
.
getInput
());
}
@
memoize
private
get
model
():
Model
{
return
this
.
instantiationService
.
createInstance
(
Model
);
}
public
createViewer
(
container
:
Builder
):
ITree
{
...
...
@@ -405,36 +417,32 @@ export class ExplorerView extends CollapsibleView {
}
private
onFileOperation
(
e
:
FileOperationEvent
):
void
{
if
(
!
this
.
root
)
{
if
(
!
this
.
isCreated
)
{
return
;
// ignore if not yet created
}
let
modelElement
:
FileStat
;
let
parent
:
FileStat
;
let
parentResource
:
URI
;
let
parentElement
:
FileStat
;
// Add
if
(
e
.
operation
===
FileOperation
.
CREATE
||
e
.
operation
===
FileOperation
.
IMPORT
||
e
.
operation
===
FileOperation
.
COPY
)
{
const
addedElement
=
e
.
target
;
parentResource
=
URI
.
file
(
paths
.
dirname
(
addedElement
.
resource
.
fsPath
));
parentElement
=
this
.
root
.
find
(
parentResource
);
const
parentResource
=
URI
.
file
(
paths
.
dirname
(
addedElement
.
resource
.
fsPath
));
const
parents
=
this
.
model
.
findAll
(
parentResource
);
if
(
parent
Element
)
{
if
(
parent
s
.
length
)
{
// Add the new file to its parent (Model)
const
childElement
=
FileStat
.
create
(
addedElement
);
parentElement
.
removeChild
(
childElement
);
// make sure to remove any previous version of the file if any
parentElement
.
addChild
(
childElement
);
// Refresh the Parent (View)
this
.
explorerViewer
.
refresh
(
parentElement
).
then
(()
=>
{
return
this
.
reveal
(
childElement
,
0.5
).
then
(()
=>
{
// Focus new element
this
.
explorerViewer
.
setFocus
(
childElement
);
});
}).
done
(
null
,
errors
.
onUnexpectedError
);
parents
.
forEach
(
p
=>
{
const
childElement
=
FileStat
.
create
(
addedElement
,
p
.
root
);
p
.
removeChild
(
childElement
);
// make sure to remove any previous version of the file if any
p
.
addChild
(
childElement
);
// Refresh the Parent (View)
this
.
explorerViewer
.
refresh
(
p
).
then
(()
=>
{
return
this
.
reveal
(
childElement
,
0.5
).
then
(()
=>
{
// Focus new element
this
.
explorerViewer
.
setFocus
(
childElement
);
});
}).
done
(
null
,
errors
.
onUnexpectedError
);
});
}
}
...
...
@@ -455,43 +463,39 @@ export class ExplorerView extends CollapsibleView {
// Handle Rename
if
(
oldParentResource
&&
newParentResource
&&
oldParentResource
.
toString
()
===
newParentResource
.
toString
())
{
modelElement
=
this
.
root
.
find
(
oldResource
);
if
(
modelElement
)
{
const
modelElements
=
this
.
model
.
findAll
(
oldResource
);
modelElements
.
forEach
(
modelElement
=>
{
// Rename File (Model)
modelElement
.
rename
(
newElement
);
// Update Parent (View)
parent
=
modelElement
.
parent
;
if
(
parent
)
{
this
.
explorerViewer
.
refresh
(
parent
).
done
(()
=>
{
// Select in Viewer if set
if
(
restoreFocus
)
{
this
.
explorerViewer
.
setFocus
(
modelElement
);
}
},
errors
.
onUnexpectedError
);
}
}
this
.
explorerViewer
.
refresh
(
modelElement
.
parent
).
done
(()
=>
{
// Select in Viewer if set
if
(
restoreFocus
)
{
this
.
explorerViewer
.
setFocus
(
modelElement
);
}
},
errors
.
onUnexpectedError
);
});
}
// Handle Move
else
if
(
oldParentResource
&&
newParentResource
)
{
const
oldParent
=
this
.
root
.
find
(
oldParentResource
);
const
newParent
=
this
.
root
.
find
(
newParentResource
);
modelElement
=
this
.
root
.
find
(
oldResource
);
const
newParents
=
this
.
model
.
findAll
(
newParentResource
);
const
modelElements
=
this
.
model
.
findAll
(
oldResource
);
if
(
oldParent
&&
newParent
&&
modelElement
)
{
if
(
newParents
.
length
&&
modelElements
.
length
)
{
// Move in Model
modelElement
.
move
(
newParent
,
(
callback
:
()
=>
void
)
=>
{
// Update old parent
this
.
explorerViewer
.
refresh
(
oldParent
,
true
).
done
(
callback
,
errors
.
onUnexpectedError
);
},
()
=>
{
// Update new parent
this
.
explorerViewer
.
refresh
(
newParent
,
true
).
done
(()
=>
this
.
explorerViewer
.
expand
(
newParent
),
errors
.
onUnexpectedError
);
modelElements
.
forEach
((
modelElement
,
index
)
=>
{
const
oldParent
=
modelElement
.
parent
;
modelElement
.
move
(
newParents
[
index
],
(
callback
:
()
=>
void
)
=>
{
// Update old parent
this
.
explorerViewer
.
refresh
(
oldParent
).
done
(
callback
,
errors
.
onUnexpectedError
);
},
()
=>
{
// Update new parent
this
.
explorerViewer
.
refresh
(
newParents
[
index
],
true
).
done
(()
=>
this
.
explorerViewer
.
expand
(
newParents
[
index
]),
errors
.
onUnexpectedError
);
});
});
}
}
...
...
@@ -499,23 +503,24 @@ export class ExplorerView extends CollapsibleView {
// Delete
else
if
(
e
.
operation
===
FileOperation
.
DELETE
)
{
modelElement
=
this
.
root
.
find
(
e
.
resource
);
if
(
modelElement
&&
modelElement
.
parent
)
{
parent
=
modelElement
.
parent
;
// Remove Element from Parent (Model)
parent
.
removeChild
(
modelElement
);
// Refresh Parent (View)
const
restoreFocus
=
this
.
explorerViewer
.
isDOMFocused
();
this
.
explorerViewer
.
refresh
(
parent
).
done
(()
=>
{
// Ensure viewer has keyboard focus if event originates from viewer
if
(
restoreFocus
)
{
this
.
explorerViewer
.
DOMFocus
();
}
},
errors
.
onUnexpectedError
);
}
const
modelElements
=
this
.
model
.
findAll
(
e
.
resource
);
modelElements
.
forEach
(
element
=>
{
if
(
element
.
parent
)
{
const
parent
=
element
.
parent
;
// Remove Element from Parent (Model)
parent
.
removeChild
(
element
);
// Refresh Parent (View)
const
restoreFocus
=
this
.
explorerViewer
.
isDOMFocused
();
this
.
explorerViewer
.
refresh
(
parent
).
done
(()
=>
{
// Ensure viewer has keyboard focus if event originates from viewer
if
(
restoreFocus
)
{
this
.
explorerViewer
.
DOMFocus
();
}
},
errors
.
onUnexpectedError
);
}
});
}
}
...
...
@@ -561,7 +566,7 @@ export class ExplorerView extends CollapsibleView {
const
added
=
e
.
getAdded
();
const
deleted
=
e
.
getDeleted
();
if
(
!
this
.
root
)
{
if
(
!
this
.
isCreated
)
{
return
false
;
}
...
...
@@ -582,8 +587,8 @@ export class ExplorerView extends CollapsibleView {
}
// Compute if parent is visible and added file not yet part of it
const
parentStat
=
this
.
root
.
find
(
URI
.
file
(
parent
));
if
(
parentStat
&&
parentStat
.
isDirectoryResolved
&&
!
this
.
root
.
find
(
change
.
resource
))
{
const
parentStat
=
this
.
model
.
findFirst
(
URI
.
file
(
parent
));
if
(
parentStat
&&
parentStat
.
isDirectoryResolved
&&
!
this
.
model
.
findFirst
(
change
.
resource
))
{
return
true
;
}
...
...
@@ -600,7 +605,7 @@ export class ExplorerView extends CollapsibleView {
continue
;
// out of workspace file
}
if
(
this
.
root
.
find
(
del
.
resource
))
{
if
(
this
.
model
.
findFirst
(
del
.
resource
))
{
return
true
;
}
}
...
...
@@ -673,7 +678,11 @@ export class ExplorerView extends CollapsibleView {
}
private
doRefresh
():
TPromise
<
void
>
{
const
targetsToResolve
:
URI
[]
=
[];
const
targetsToResolve
:
{
root
:
FileStat
,
resource
:
URI
,
options
:
{
resolveTo
:
URI
[]
}
}[]
=
[];
this
.
model
.
roots
.
forEach
(
root
=>
{
const
rootAndTargets
=
{
root
,
resource
:
root
.
resource
,
options
:
{
resolveTo
:
[]
}
};
targetsToResolve
.
push
(
rootAndTargets
);
});
let
targetsToExpand
:
URI
[]
=
[];
if
(
this
.
settings
[
ExplorerView
.
MEMENTO_EXPANDED_FOLDER_RESOURCES
])
{
...
...
@@ -681,51 +690,55 @@ export class ExplorerView extends CollapsibleView {
}
// First time refresh: Receive target through active editor input or selection and also include settings from previous session
if
(
!
this
.
root
)
{
if
(
!
this
.
isCreated
)
{
const
activeFile
=
this
.
getActiveFile
();
if
(
activeFile
)
{
targetsToResolve
.
push
(
activeFile
);
const
root
=
this
.
contextService
.
getRoot
(
activeFile
);
if
(
root
)
{
const
found
=
targetsToResolve
.
filter
(
t
=>
t
.
root
.
resource
.
toString
()
===
root
.
toString
()).
pop
();
found
.
options
.
resolveTo
.
push
(
activeFile
);
}
}
if
(
targetsToExpand
.
length
)
{
targetsToResolve
.
push
(...
targetsToExpand
);
}
targetsToExpand
.
forEach
(
toExpand
=>
{
const
root
=
this
.
contextService
.
getRoot
(
toExpand
);
if
(
root
)
{
const
found
=
targetsToResolve
.
filter
(
ttr
=>
ttr
.
resource
.
toString
()
===
root
.
toString
()).
pop
();
found
.
options
.
resolveTo
.
push
(
toExpand
);
}
});
}
// Subsequent refresh: Receive targets through expanded folders in tree
else
{
this
.
getResolvedDirectories
(
this
.
root
,
targetsToResolve
);
targetsToResolve
.
forEach
(
t
=>
{
this
.
getResolvedDirectories
(
t
.
root
,
t
.
options
.
resolveTo
);
});
}
// Load Root Stat with given target path configured
const
options
:
IResolveFileOptions
=
{
resolveTo
:
targetsToResolve
};
const
promise
=
this
.
fileService
.
resolveFile
(
this
.
contextService
.
getWorkspace
().
resource
,
options
).
then
(
stat
=>
{
let
explorerPromise
:
TPromise
<
void
>
;
const
promise
=
this
.
fileService
.
resolveFiles
(
targetsToResolve
).
then
(
stats
=>
{
// Convert to model
const
modelStat
=
FileStat
.
create
(
stat
,
options
.
resolveTo
);
// First time refresh: The stat becomes the input of the viewer
if
(
!
this
.
root
)
{
explorerPromise
=
this
.
explorerViewer
.
setInput
(
modelStat
).
then
(()
=>
{
// Make sure to expand all folders that where expanded in the previous session
if
(
targetsToExpand
)
{
return
this
.
explorerViewer
.
expandAll
(
targetsToExpand
.
map
(
expand
=>
this
.
root
.
find
(
expand
)));
}
const
modelStats
=
stats
.
map
((
stat
,
index
)
=>
FileStat
.
create
(
stat
,
targetsToResolve
[
index
].
root
.
resource
,
targetsToResolve
[
index
].
options
.
resolveTo
));
// Subsequent refresh: Merge stat into our local model and refresh tree
modelStats
.
forEach
((
modelStat
,
index
)
=>
FileStat
.
mergeLocalWithDisk
(
modelStat
,
this
.
model
.
roots
[
index
]));
return
TPromise
.
as
(
null
);
});
const
input
=
this
.
model
.
roots
.
length
===
1
?
this
.
model
.
roots
[
0
]
:
this
.
model
;
if
(
input
===
this
.
explorerViewer
.
getInput
())
{
return
this
.
explorerViewer
.
refresh
();
}
//
Subsequent refresh: Merge stat into our local model and refresh tree
else
{
FileStat
.
mergeLocalWithDisk
(
modelStat
,
this
.
root
);
//
First time refresh: The stat becomes the input of the viewer
// Display roots only when there is more than 1 root
return
this
.
explorerViewer
.
setInput
(
input
).
then
(()
=>
{
explorerPromise
=
this
.
explorerViewer
.
refresh
(
this
.
root
);
}
// Make sure to expand all folders that where expanded in the previous session
if
(
targetsToExpand
)
{
return
this
.
explorerViewer
.
expandAll
(
targetsToExpand
.
map
(
expand
=>
this
.
model
.
findFirst
(
expand
)));
}
return
explorerPromise
;
return
TPromise
.
as
(
null
);
});
},
(
e
:
any
)
=>
TPromise
.
wrapError
(
e
));
this
.
progressService
.
showWhile
(
promise
,
this
.
partService
.
isCreated
()
?
800
:
3200
/* less ugly initial startup */
);
...
...
@@ -778,27 +791,28 @@ export class ExplorerView extends CollapsibleView {
}
// First try to get the stat object from the input to avoid a roundtrip
if
(
!
this
.
root
)
{
if
(
!
this
.
isCreated
)
{
return
TPromise
.
as
(
null
);
}
const
fileStat
=
this
.
root
.
find
(
resource
);
const
fileStat
=
this
.
model
.
findFirst
(
resource
);
if
(
fileStat
)
{
return
this
.
doSelect
(
fileStat
,
reveal
);
}
// Stat needs to be resolved first and then revealed
const
options
:
IResolveFileOptions
=
{
resolveTo
:
[
resource
]
};
return
this
.
fileService
.
resolveFile
(
this
.
contextService
.
getWorkspace
().
resource
,
options
).
then
(
stat
=>
{
const
rootUri
=
this
.
contextService
.
getRoot
(
resource
)
||
this
.
model
.
roots
[
0
].
resource
;
return
this
.
fileService
.
resolveFile
(
rootUri
,
options
).
then
(
stat
=>
{
// Convert to model
const
modelStat
=
FileStat
.
create
(
stat
,
options
.
resolveTo
);
const
modelStat
=
FileStat
.
create
(
stat
,
rootUri
,
options
.
resolveTo
);
const
root
=
this
.
model
.
roots
.
filter
(
r
=>
r
.
resource
.
toString
()
===
rootUri
.
toString
()).
pop
();
// Update Input with disk Stat
FileStat
.
mergeLocalWithDisk
(
modelStat
,
this
.
root
);
FileStat
.
mergeLocalWithDisk
(
modelStat
,
root
);
// Select and Reveal
return
this
.
explorerViewer
.
refresh
(
this
.
root
).
then
(()
=>
this
.
doSelect
(
this
.
root
.
find
(
resource
),
reveal
));
return
this
.
explorerViewer
.
refresh
(
root
).
then
(()
=>
this
.
doSelect
(
root
.
find
(
resource
),
reveal
));
},
(
e
:
any
)
=>
this
.
messageService
.
show
(
Severity
.
Error
,
e
));
}
...
...
@@ -849,7 +863,7 @@ export class ExplorerView extends CollapsibleView {
public
shutdown
():
void
{
// Keep list of expanded folders to restore on next load
if
(
this
.
root
)
{
if
(
this
.
isCreated
)
{
const
expanded
=
this
.
explorerViewer
.
getExpandedElements
()
.
filter
((
e
:
FileStat
)
=>
e
.
resource
.
toString
()
!==
this
.
contextService
.
getWorkspace
().
resource
.
toString
())
.
map
((
e
:
FileStat
)
=>
e
.
resource
.
toString
());
...
...
src/vs/workbench/parts/files/browser/views/explorerViewer.ts
浏览文件 @
4f33f591
...
...
@@ -31,7 +31,7 @@ import { DuplicateFileAction, ImportFileAction, IEditableData, IFileViewletState
import
{
IDataSource
,
ITree
,
IAccessibilityProvider
,
IRenderer
,
ContextMenuEvent
,
ISorter
,
IFilter
,
IDragAndDrop
,
IDragAndDropData
,
IDragOverReaction
,
DRAG_OVER_ACCEPT_BUBBLE_DOWN
,
DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY
,
DRAG_OVER_ACCEPT_BUBBLE_UP
,
DRAG_OVER_ACCEPT_BUBBLE_UP_COPY
,
DRAG_OVER_REJECT
}
from
'
vs/base/parts/tree/browser/tree
'
;
import
{
DesktopDragAndDropData
,
ExternalElementsDragAndDropData
}
from
'
vs/base/parts/tree/browser/treeDnd
'
;
import
{
ClickBehavior
,
DefaultController
}
from
'
vs/base/parts/tree/browser/treeDefaults
'
;
import
{
FileStat
,
NewStatPlaceholder
}
from
'
vs/workbench/parts/files/common/explorerView
Model
'
;
import
{
FileStat
,
NewStatPlaceholder
,
Model
}
from
'
vs/workbench/parts/files/common/explorer
Model
'
;
import
{
DragMouseEvent
,
IMouseEvent
}
from
'
vs/base/browser/mouseEvent
'
;
import
{
IWorkbenchEditorService
}
from
'
vs/workbench/services/editor/common/editorService
'
;
import
{
IPartService
}
from
'
vs/workbench/services/part/common/partService
'
;
...
...
@@ -60,15 +60,22 @@ export class FileDataSource implements IDataSource {
@
IWorkspaceContextService
private
contextService
:
IWorkspaceContextService
)
{
}
public
getId
(
tree
:
ITree
,
stat
:
FileStat
):
string
{
return
stat
.
getId
();
public
getId
(
tree
:
ITree
,
stat
:
FileStat
|
Model
):
string
{
if
(
stat
instanceof
Model
)
{
return
'
model
'
;
}
return
`
${
stat
.
root
.
toString
()}
:
${
stat
.
getId
()}
`
;
}
public
hasChildren
(
tree
:
ITree
,
stat
:
FileStat
):
boolean
{
return
stat
.
isDirectory
;
public
hasChildren
(
tree
:
ITree
,
stat
:
FileStat
|
Model
):
boolean
{
return
stat
instanceof
Model
||
(
stat
instanceof
FileStat
&&
stat
.
isDirectory
)
;
}
public
getChildren
(
tree
:
ITree
,
stat
:
FileStat
):
TPromise
<
FileStat
[]
>
{
public
getChildren
(
tree
:
ITree
,
stat
:
FileStat
|
Model
):
TPromise
<
FileStat
[]
>
{
if
(
stat
instanceof
Model
)
{
return
TPromise
.
as
(
stat
.
roots
);
}
// Return early if stat is already resolved
if
(
stat
.
isDirectoryResolved
)
{
...
...
@@ -82,7 +89,7 @@ export class FileDataSource implements IDataSource {
const
promise
=
this
.
fileService
.
resolveFile
(
stat
.
resource
,
{
resolveSingleChildDescendants
:
true
}).
then
(
dirStat
=>
{
// Convert to view model
const
modelDirStat
=
FileStat
.
create
(
dirStat
);
const
modelDirStat
=
FileStat
.
create
(
dirStat
,
stat
.
root
);
// Add children to folder
for
(
let
i
=
0
;
i
<
modelDirStat
.
children
.
length
;
i
++
)
{
...
...
@@ -104,19 +111,18 @@ export class FileDataSource implements IDataSource {
}
}
public
getParent
(
tree
:
ITree
,
stat
:
FileStat
):
TPromise
<
FileStat
>
{
public
getParent
(
tree
:
ITree
,
stat
:
FileStat
|
Model
):
TPromise
<
FileStat
>
{
if
(
!
stat
)
{
return
TPromise
.
as
(
null
);
// can be null if nothing selected in the tree
}
// Return if root reached
const
workspace
=
this
.
contextService
.
getWorkspace
();
if
(
workspace
&&
stat
.
resource
.
toString
()
===
workspace
.
resource
.
toString
())
{
if
(
tree
.
getInput
()
===
stat
)
{
return
TPromise
.
as
(
null
);
}
// Return if parent already resolved
if
(
stat
.
parent
)
{
if
(
stat
instanceof
FileStat
&&
stat
.
parent
)
{
return
TPromise
.
as
(
stat
.
parent
);
}
...
...
@@ -404,7 +410,7 @@ export class FileController extends DefaultController {
this
.
state
=
state
;
}
public
onLeftClick
(
tree
:
ITree
,
stat
:
FileStat
,
event
:
IMouseEvent
,
origin
:
string
=
'
mouse
'
):
boolean
{
public
onLeftClick
(
tree
:
ITree
,
stat
:
FileStat
|
Model
,
event
:
IMouseEvent
,
origin
:
string
=
'
mouse
'
):
boolean
{
const
payload
=
{
origin
:
origin
};
const
isDoubleClick
=
(
origin
===
'
mouse
'
&&
event
.
detail
===
2
);
...
...
@@ -421,8 +427,7 @@ export class FileController extends DefaultController {
}
// Handle root
const
workspace
=
this
.
contextService
.
getWorkspace
();
if
(
workspace
&&
stat
.
resource
.
toString
()
===
workspace
.
resource
.
toString
())
{
if
(
stat
instanceof
Model
)
{
tree
.
clearFocus
(
payload
);
tree
.
clearSelection
(
payload
);
...
...
@@ -539,6 +544,15 @@ export class FileSorter implements ISorter {
return
1
;
}
// Do not sort roots
if
(
statA
.
isRoot
)
{
return
-
1
;
}
if
(
statB
.
isRoot
)
{
return
1
;
}
return
comparers
.
compareFileNames
(
statA
.
name
,
statB
.
name
);
}
}
...
...
@@ -558,6 +572,7 @@ export class FileFilter implements IFilter {
const
excludesConfig
=
(
configuration
&&
configuration
.
files
&&
configuration
.
files
.
exclude
)
||
Object
.
create
(
null
);
const
needsRefresh
=
!
objects
.
equals
(
this
.
hiddenExpression
,
excludesConfig
);
// This needs to be per folder
this
.
hiddenExpression
=
objects
.
clone
(
excludesConfig
);
// do not keep the config, as it gets mutated under our hoods
return
needsRefresh
;
...
...
@@ -619,6 +634,9 @@ export class FileDragAndDrop implements IDragAndDrop {
}
public
getDragURI
(
tree
:
ITree
,
stat
:
FileStat
):
string
{
if
(
this
.
contextService
.
getWorkspace2
().
roots
.
some
(
r
=>
r
.
toString
()
===
stat
.
resource
.
toString
()))
{
return
null
;
// Can not move root folder
}
if
(
stat
.
isDirectory
)
{
return
URI
.
from
({
scheme
:
'
folder
'
,
path
:
stat
.
resource
.
fsPath
}).
toString
();
// indicates that we are dragging a folder
}
...
...
@@ -656,8 +674,8 @@ export class FileDragAndDrop implements IDragAndDrop {
}
}
public
onDragOver
(
tree
:
ITree
,
data
:
IDragAndDropData
,
target
:
FileStat
,
originalEvent
:
DragMouseEvent
):
IDragOverReaction
{
if
(
!
this
.
dropEnabled
)
{
public
onDragOver
(
tree
:
ITree
,
data
:
IDragAndDropData
,
target
:
FileStat
|
Model
,
originalEvent
:
DragMouseEvent
):
IDragOverReaction
{
if
(
!
this
.
dropEnabled
||
target
instanceof
Model
)
{
return
DRAG_OVER_REJECT
;
}
...
...
@@ -719,8 +737,8 @@ export class FileDragAndDrop implements IDragAndDrop {
return
fromDesktop
||
isCopy
?
DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY
(
true
)
:
DRAG_OVER_ACCEPT_BUBBLE_DOWN
(
true
);
}
const
workspace
=
this
.
contextService
.
getWorkspace
();
if
(
workspace
&&
target
.
resource
.
toString
()
!==
workspace
.
resource
.
toString
(
))
{
const
workspace
=
this
.
contextService
.
getWorkspace
2
();
if
(
workspace
&&
workspace
.
roots
.
every
(
r
=>
r
.
toString
()
!==
target
.
resource
.
toString
()
))
{
return
fromDesktop
||
isCopy
?
DRAG_OVER_ACCEPT_BUBBLE_UP_COPY
:
DRAG_OVER_ACCEPT_BUBBLE_UP
;
}
...
...
src/vs/workbench/parts/files/browser/views/openEditorsView.ts
浏览文件 @
4f33f591
...
...
@@ -22,7 +22,7 @@ import { CollapsibleView, IViewletViewOptions } from 'vs/workbench/parts/views/b
import
{
IFilesConfiguration
,
VIEWLET_ID
,
OpenEditorsFocussedContext
,
ExplorerFocussedContext
}
from
'
vs/workbench/parts/files/common/files
'
;
import
{
ITextFileService
,
AutoSaveMode
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
IViewletService
}
from
'
vs/workbench/services/viewlet/browser/viewlet
'
;
import
{
OpenEditor
}
from
'
vs/workbench/parts/files/common/explorer
View
Model
'
;
import
{
OpenEditor
}
from
'
vs/workbench/parts/files/common/explorerModel
'
;
import
{
Renderer
,
DataSource
,
Controller
,
AccessibilityProvider
,
ActionProvider
,
DragAndDrop
}
from
'
vs/workbench/parts/files/browser/views/openEditorsViewer
'
;
import
{
IUntitledEditorService
}
from
'
vs/workbench/services/untitled/common/untitledEditorService
'
;
import
{
CloseAllEditorsAction
}
from
'
vs/workbench/browser/parts/editor/editorActions
'
;
...
...
src/vs/workbench/parts/files/browser/views/openEditorsViewer.ts
浏览文件 @
4f33f591
...
...
@@ -22,7 +22,7 @@ import { IEditorGroupService } from 'vs/workbench/services/group/common/groupSer
import
{
IContextMenuService
}
from
'
vs/platform/contextview/browser/contextView
'
;
import
{
IKeybindingService
}
from
'
vs/platform/keybinding/common/keybinding
'
;
import
{
IEditorGroup
,
IEditorStacksModel
}
from
'
vs/workbench/common/editor
'
;
import
{
OpenEditor
}
from
'
vs/workbench/parts/files/common/explorer
View
Model
'
;
import
{
OpenEditor
}
from
'
vs/workbench/parts/files/common/explorerModel
'
;
import
{
ContributableActionProvider
}
from
'
vs/workbench/browser/actions
'
;
import
{
explorerItemToFileResource
}
from
'
vs/workbench/parts/files/common/files
'
;
import
{
ITextFileService
,
AutoSaveMode
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
...
...
src/vs/workbench/parts/files/common/explorer
View
Model.ts
→
src/vs/workbench/parts/files/common/explorerModel.ts
浏览文件 @
4f33f591
...
...
@@ -7,11 +7,12 @@
import
URI
from
'
vs/base/common/uri
'
;
import
paths
=
require
(
'
vs/base/common/paths
'
);
import
{
ResourceMap
}
from
'
vs/base/common/map
'
;
import
{
isLinux
}
from
'
vs/base/common/platform
'
;
import
{
IFileStat
,
isParent
}
from
'
vs/platform/files/common/files
'
;
import
{
IEditorInput
}
from
'
vs/platform/editor/common/editor
'
;
import
{
IWorkspaceContextService
}
from
'
vs/platform/workspace/common/workspace
'
;
import
{
IEditorGroup
,
toResource
}
from
'
vs/workbench/common/editor
'
;
import
{
ResourceMap
}
from
'
vs/base/common/map
'
;
import
{
isLinux
}
from
'
vs/base/common/platform
'
;
export
enum
StatType
{
FILE
,
...
...
@@ -19,6 +20,41 @@ export enum StatType {
ANY
}
export
class
Model
{
private
_roots
:
FileStat
[];
constructor
(
@
IWorkspaceContextService
private
contextService
:
IWorkspaceContextService
)
{
const
setRoots
=
()
=>
this
.
_roots
=
this
.
contextService
.
getWorkspace2
().
roots
.
map
(
uri
=>
new
FileStat
(
uri
,
uri
));
this
.
contextService
.
onDidChangeWorkspaceRoots
(()
=>
setRoots
());
setRoots
();
}
public
get
roots
():
FileStat
[]
{
return
this
.
_roots
;
}
/**
* Returns a child stat from this stat that matches with the provided path.
* Starts matching from the first root.
* Will return "null" in case the child does not exist.
*/
public
findAll
(
resource
:
URI
):
FileStat
[]
{
return
this
.
roots
.
map
(
root
=>
root
.
find
(
resource
)).
filter
(
stat
=>
!!
stat
);
}
public
findFirst
(
resource
:
URI
):
FileStat
{
for
(
let
root
of
this
.
roots
)
{
const
result
=
root
.
find
(
resource
);
if
(
result
)
{
return
result
;
}
}
return
null
;
}
}
export
class
FileStat
implements
IFileStat
{
public
resource
:
URI
;
public
name
:
string
;
...
...
@@ -31,7 +67,7 @@ export class FileStat implements IFileStat {
public
isDirectoryResolved
:
boolean
;
constructor
(
resource
:
URI
,
isDirectory
?:
boolean
,
hasChildren
?:
boolean
,
name
:
string
=
paths
.
basename
(
resource
.
fsPath
),
mtime
?:
number
,
etag
?:
string
)
{
constructor
(
resource
:
URI
,
public
root
:
URI
,
isDirectory
?:
boolean
,
hasChildren
?:
boolean
,
name
:
string
=
paths
.
basename
(
resource
.
fsPath
),
mtime
?:
number
,
etag
?:
string
)
{
this
.
resource
=
resource
;
this
.
name
=
name
;
this
.
isDirectory
=
!!
isDirectory
;
...
...
@@ -51,8 +87,12 @@ export class FileStat implements IFileStat {
return
this
.
resource
.
toString
();
}
public
static
create
(
raw
:
IFileStat
,
resolveTo
?:
URI
[]):
FileStat
{
const
stat
=
new
FileStat
(
raw
.
resource
,
raw
.
isDirectory
,
raw
.
hasChildren
,
raw
.
name
,
raw
.
mtime
,
raw
.
etag
);
public
get
isRoot
():
boolean
{
return
this
.
resource
.
toString
()
===
this
.
root
.
toString
();
}
public
static
create
(
raw
:
IFileStat
,
root
:
URI
,
resolveTo
?:
URI
[]):
FileStat
{
const
stat
=
new
FileStat
(
raw
.
resource
,
root
,
raw
.
isDirectory
,
raw
.
hasChildren
,
raw
.
name
,
raw
.
mtime
,
raw
.
etag
);
// Recursively add children if present
if
(
stat
.
isDirectory
)
{
...
...
@@ -67,7 +107,7 @@ export class FileStat implements IFileStat {
// Recurse into children
if
(
raw
.
children
)
{
for
(
let
i
=
0
,
len
=
raw
.
children
.
length
;
i
<
len
;
i
++
)
{
const
child
=
FileStat
.
create
(
raw
.
children
[
i
],
resolveTo
);
const
child
=
FileStat
.
create
(
raw
.
children
[
i
],
r
oot
,
r
esolveTo
);
child
.
parent
=
stat
;
stat
.
children
.
push
(
child
);
stat
.
hasChildren
=
stat
.
children
.
length
>
0
;
...
...
@@ -107,9 +147,11 @@ export class FileStat implements IFileStat {
// Map resource => stat
const
oldLocalChildren
=
new
ResourceMap
<
FileStat
>
();
local
.
children
.
forEach
((
localChild
:
FileStat
)
=>
{
oldLocalChildren
.
set
(
localChild
.
resource
,
localChild
);
});
if
(
local
.
children
)
{
local
.
children
.
forEach
((
localChild
:
FileStat
)
=>
{
oldLocalChildren
.
set
(
localChild
.
resource
,
localChild
);
});
}
// Clear current children
local
.
children
=
[];
...
...
@@ -275,7 +317,7 @@ export class NewStatPlaceholder extends FileStat {
private
directoryPlaceholder
:
boolean
;
constructor
(
isDirectory
:
boolean
)
{
super
(
URI
.
file
(
''
));
super
(
URI
.
file
(
''
)
,
URI
.
file
(
''
)
);
this
.
id
=
NewStatPlaceholder
.
ID
++
;
this
.
isDirectoryResolved
=
isDirectory
;
...
...
src/vs/workbench/parts/files/common/files.ts
浏览文件 @
4f33f591
...
...
@@ -8,7 +8,7 @@ import URI from 'vs/base/common/uri';
import
{
IEditorOptions
}
from
'
vs/editor/common/config/editorOptions
'
;
import
{
IWorkbenchEditorConfiguration
}
from
'
vs/workbench/common/editor
'
;
import
{
IFilesConfiguration
}
from
'
vs/platform/files/common/files
'
;
import
{
FileStat
,
OpenEditor
}
from
'
vs/workbench/parts/files/common/explorer
View
Model
'
;
import
{
FileStat
,
OpenEditor
}
from
'
vs/workbench/parts/files/common/explorerModel
'
;
import
{
ContextKeyExpr
,
RawContextKey
}
from
'
vs/platform/contextkey/common/contextkey
'
;
/**
...
...
src/vs/workbench/parts/files/test/browser/explorer
View
Model.test.ts
→
src/vs/workbench/parts/files/test/browser/explorerModel.test.ts
浏览文件 @
4f33f591
...
...
@@ -11,10 +11,10 @@ import { isLinux, isWindows } from 'vs/base/common/platform';
import
URI
from
'
vs/base/common/uri
'
;
import
{
join
}
from
'
vs/base/common/paths
'
;
import
{
validateFileName
}
from
'
vs/workbench/parts/files/browser/fileActions
'
;
import
{
FileStat
}
from
'
vs/workbench/parts/files/common/explorer
View
Model
'
;
import
{
FileStat
}
from
'
vs/workbench/parts/files/common/explorerModel
'
;
function
createStat
(
path
,
name
,
isFolder
,
hasChildren
,
size
,
mtime
)
{
return
new
FileStat
(
toResource
(
path
),
isFolder
,
hasChildren
,
name
,
mtime
);
return
new
FileStat
(
toResource
(
path
),
toResource
(
path
),
isFolder
,
hasChildren
,
name
,
mtime
);
}
function
toResource
(
path
)
{
...
...
@@ -246,20 +246,20 @@ suite('Files - View Model', () => {
test
(
'
Merge Local with Disk
'
,
function
()
{
const
d
=
new
Date
().
toUTCString
();
const
merge1
=
new
FileStat
(
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path/to
'
)),
true
,
false
,
'
to
'
,
Date
.
now
(),
d
);
const
merge2
=
new
FileStat
(
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path/to
'
)),
true
,
false
,
'
to
'
,
Date
.
now
(),
new
Date
(
0
).
toUTCString
());
const
merge1
=
new
FileStat
(
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path/to
'
)),
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path
'
)),
true
,
false
,
'
to
'
,
Date
.
now
(),
d
);
const
merge2
=
new
FileStat
(
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path/to
'
)),
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path
'
)),
true
,
false
,
'
to
'
,
Date
.
now
(),
new
Date
(
0
).
toUTCString
());
// Merge Properties
FileStat
.
mergeLocalWithDisk
(
merge2
,
merge1
);
assert
.
strictEqual
(
merge1
.
mtime
,
merge2
.
mtime
);
// Merge Child when isDirectoryResolved=false is a no-op
merge2
.
addChild
(
new
FileStat
(
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path/to/foo.html
'
)),
true
,
false
,
'
foo.html
'
,
Date
.
now
(),
d
));
merge2
.
addChild
(
new
FileStat
(
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path/to/foo.html
'
)),
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path
'
)),
true
,
false
,
'
foo.html
'
,
Date
.
now
(),
d
));
FileStat
.
mergeLocalWithDisk
(
merge2
,
merge1
);
assert
.
strictEqual
(
merge1
.
children
.
length
,
0
);
// Merge Child with isDirectoryResolved=true
const
child
=
new
FileStat
(
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path/to/foo.html
'
)),
true
,
false
,
'
foo.html
'
,
Date
.
now
(),
d
);
const
child
=
new
FileStat
(
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path/to/foo.html
'
)),
URI
.
file
(
join
(
'
C:
\\
'
,
'
/path
'
)),
true
,
false
,
'
foo.html
'
,
Date
.
now
(),
d
);
merge2
.
removeChild
(
child
);
merge2
.
addChild
(
child
);
merge2
.
isDirectoryResolved
=
true
;
...
...
src/vs/workbench/services/configuration/node/configuration.ts
浏览文件 @
4f33f591
...
...
@@ -642,4 +642,4 @@ class Configuration<T> extends BaseConfiguration<T> {
return
true
;
}
}
\ No newline at end of file
}
src/vs/workbench/services/files/electron-browser/fileService.ts
浏览文件 @
4f33f591
...
...
@@ -198,6 +198,10 @@ export class FileService implements IFileService {
return
this
.
raw
.
resolveFile
(
resource
,
options
);
}
public
resolveFiles
(
toResolve
:
{
resource
:
uri
,
options
?:
IResolveFileOptions
}[]):
TPromise
<
IFileStat
[]
>
{
return
this
.
raw
.
resolveFiles
(
toResolve
);
}
public
existsFile
(
resource
:
uri
):
TPromise
<
boolean
>
{
return
this
.
raw
.
existsFile
(
resource
);
}
...
...
src/vs/workbench/services/files/node/fileService.ts
浏览文件 @
4f33f591
...
...
@@ -156,6 +156,10 @@ export class FileService implements IFileService {
return
this
.
resolve
(
resource
,
options
);
}
public
resolveFiles
(
toResolve
:
{
resource
:
uri
,
options
?:
IResolveFileOptions
}[]):
TPromise
<
IFileStat
[]
>
{
return
TPromise
.
join
(
toResolve
.
map
(
resourceAndOptions
=>
this
.
resolve
(
resourceAndOptions
.
resource
,
resourceAndOptions
.
options
)));
}
public
existsFile
(
resource
:
uri
):
TPromise
<
boolean
>
{
return
this
.
resolveFile
(
resource
).
then
(()
=>
true
,
()
=>
false
);
}
...
...
src/vs/workbench/test/workbenchTestServices.ts
浏览文件 @
4f33f591
...
...
@@ -670,6 +670,10 @@ export class TestFileService implements IFileService {
});
}
resolveFiles
(
toResolve
:
{
resource
:
URI
,
options
?:
IResolveFileOptions
}[]):
TPromise
<
IFileStat
[]
>
{
return
TPromise
.
join
(
toResolve
.
map
(
resourceAndOption
=>
this
.
resolveFile
(
resourceAndOption
.
resource
,
resourceAndOption
.
options
)));
}
existsFile
(
resource
:
URI
):
TPromise
<
boolean
>
{
return
TPromise
.
as
(
null
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录