Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
9b6ae0ca
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,发现更多精彩内容 >>
提交
9b6ae0ca
编写于
1月 15, 2020
作者:
B
Benjamin Pasero
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
textfiles - reduce service methods that are not needed anymore
上级
3d5b61c8
变更
11
显示空白变更内容
内联
并排
Showing
11 changed file
with
162 addition
and
251 deletion
+162
-251
src/vs/workbench/contrib/backup/test/electron-browser/backupOnShutdown.test.ts
...rib/backup/test/electron-browser/backupOnShutdown.test.ts
+7
-5
src/vs/workbench/contrib/files/browser/views/explorerViewer.ts
...s/workbench/contrib/files/browser/views/explorerViewer.ts
+5
-3
src/vs/workbench/contrib/search/browser/replaceService.ts
src/vs/workbench/contrib/search/browser/replaceService.ts
+54
-55
src/vs/workbench/services/configuration/common/configurationEditingService.ts
...vices/configuration/common/configurationEditingService.ts
+1
-1
src/vs/workbench/services/textfile/browser/textFileService.ts
...vs/workbench/services/textfile/browser/textFileService.ts
+40
-107
src/vs/workbench/services/textfile/common/textfiles.ts
src/vs/workbench/services/textfile/common/textfiles.ts
+2
-25
src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts
...kbench/services/textfile/test/textFileEditorModel.test.ts
+2
-2
src/vs/workbench/services/textfile/test/textFileService.test.ts
.../workbench/services/textfile/test/textFileService.test.ts
+33
-53
src/vs/workbench/services/workingCopy/common/workingCopyService.ts
...rkbench/services/workingCopy/common/workingCopyService.ts
+8
-0
src/vs/workbench/services/workingCopy/test/common/workingCopyService.test.ts
...rvices/workingCopy/test/common/workingCopyService.test.ts
+6
-0
src/vs/workbench/test/workbenchTestServices.ts
src/vs/workbench/test/workbenchTestServices.ts
+4
-0
未找到文件。
src/vs/workbench/contrib/backup/test/electron-browser/backupOnShutdown.test.ts
浏览文件 @
9b6ae0ca
...
...
@@ -22,6 +22,7 @@ import { IFilesConfigurationService } from 'vs/workbench/services/filesConfigura
import
{
IFileDialogService
,
ConfirmResult
}
from
'
vs/platform/dialogs/common/dialogs
'
;
import
{
BackupOnShutdown
}
from
'
vs/workbench/contrib/backup/electron-browser/backupOnShutdown
'
;
import
{
IBackupFileService
}
from
'
vs/workbench/services/backup/common/backup
'
;
import
{
IWorkingCopyService
}
from
'
vs/workbench/services/workingCopy/common/workingCopyService
'
;
class
ServiceAccessor
{
constructor
(
...
...
@@ -34,7 +35,8 @@ class ServiceAccessor {
@
IFileService
public
fileService
:
TestFileService
,
@
IElectronService
public
electronService
:
TestElectronService
,
@
IFileDialogService
public
fileDialogService
:
TestFileDialogService
,
@
IBackupFileService
public
backupFileService
:
TestBackupFileService
@
IBackupFileService
public
backupFileService
:
TestBackupFileService
,
@
IWorkingCopyService
public
workingCopyService
:
IWorkingCopyService
)
{
}
}
...
...
@@ -94,7 +96,7 @@ suite('BackupOnShutdown', () => {
await
model
.
load
();
model
.
textEditorModel
!
.
setValue
(
'
foo
'
);
assert
.
equal
(
accessor
.
textFileService
.
getDirty
().
length
,
1
);
assert
.
equal
(
accessor
.
workingCopyService
.
dirtyCount
,
1
);
const
event
=
new
BeforeShutdownEventImpl
();
accessor
.
lifecycleService
.
fireWillShutdown
(
event
);
...
...
@@ -110,7 +112,7 @@ suite('BackupOnShutdown', () => {
await
model
.
load
();
model
.
textEditorModel
!
.
setValue
(
'
foo
'
);
assert
.
equal
(
accessor
.
textFileService
.
getDirty
().
length
,
1
);
assert
.
equal
(
accessor
.
workingCopyService
.
dirtyCount
,
1
);
const
event
=
new
BeforeShutdownEventImpl
();
accessor
.
lifecycleService
.
fireWillShutdown
(
event
);
...
...
@@ -135,7 +137,7 @@ suite('BackupOnShutdown', () => {
await
model
.
load
();
model
.
textEditorModel
!
.
setValue
(
'
foo
'
);
assert
.
equal
(
accessor
.
textFileService
.
getDirty
().
length
,
1
);
assert
.
equal
(
accessor
.
workingCopyService
.
dirtyCount
,
1
);
const
event
=
new
BeforeShutdownEventImpl
();
accessor
.
lifecycleService
.
fireWillShutdown
(
event
);
...
...
@@ -269,7 +271,7 @@ suite('BackupOnShutdown', () => {
await
model
.
load
();
model
.
textEditorModel
!
.
setValue
(
'
foo
'
);
assert
.
equal
(
accessor
.
textFileService
.
getDirty
().
length
,
1
);
assert
.
equal
(
accessor
.
workingCopyService
.
dirtyCount
,
1
);
const
event
=
new
BeforeShutdownEventImpl
();
event
.
reason
=
shutdownReason
;
...
...
src/vs/workbench/contrib/files/browser/views/explorerViewer.ts
浏览文件 @
9b6ae0ca
...
...
@@ -55,6 +55,7 @@ import { ILabelService } from 'vs/platform/label/common/label';
import
{
isNumber
}
from
'
vs/base/common/types
'
;
import
{
domEvent
}
from
'
vs/base/browser/event
'
;
import
{
IEditableData
}
from
'
vs/workbench/common/views
'
;
import
{
IWorkingCopyService
}
from
'
vs/workbench/services/workingCopy/common/workingCopyService
'
;
export
class
ExplorerDelegate
implements
IListVirtualDelegate
<
ExplorerItem
>
{
...
...
@@ -642,7 +643,8 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
@
IInstantiationService
private
instantiationService
:
IInstantiationService
,
@
ITextFileService
private
textFileService
:
ITextFileService
,
@
IHostService
private
hostService
:
IHostService
,
@
IWorkspaceEditingService
private
workspaceEditingService
:
IWorkspaceEditingService
@
IWorkspaceEditingService
private
workspaceEditingService
:
IWorkspaceEditingService
,
@
IWorkingCopyService
private
workingCopyService
:
IWorkingCopyService
)
{
this
.
toDispose
=
[];
...
...
@@ -946,8 +948,8 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
// if the target exists and is dirty, make sure to revert it. otherwise the dirty contents
// of the target file would replace the contents of the added file. since we already
// confirmed the overwrite before, this is OK.
if
(
this
.
textFile
Service
.
isDirty
(
targetFile
))
{
await
this
.
textFileService
.
revertAll
([
targetFile
],
{
soft
:
true
}
);
if
(
this
.
workingCopy
Service
.
isDirty
(
targetFile
))
{
await
Promise
.
all
(
this
.
workingCopyService
.
getWorkingCopies
(
targetFile
).
map
(
workingCopy
=>
workingCopy
.
revert
({
soft
:
true
}))
);
}
const
copyTarget
=
joinPath
(
target
.
resource
,
basename
(
sourceFile
));
...
...
src/vs/workbench/contrib/search/browser/replaceService.ts
浏览文件 @
9b6ae0ca
...
...
@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import
*
as
nls
from
'
vs/nls
'
;
import
*
as
errors
from
'
vs/base/common/errors
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
*
as
network
from
'
vs/base/common/network
'
;
import
{
Disposable
}
from
'
vs/base/common/lifecycle
'
;
...
...
@@ -65,11 +64,10 @@ class ReplacePreviewModel extends Disposable {
super
();
}
resolve
(
replacePreviewUri
:
URI
):
Promise
<
ITextModel
>
{
async
resolve
(
replacePreviewUri
:
URI
):
Promise
<
ITextModel
>
{
const
fileResource
=
toFileResource
(
replacePreviewUri
);
const
fileMatch
=
<
FileMatch
>
this
.
searchWorkbenchService
.
searchModel
.
searchResult
.
matches
().
filter
(
match
=>
match
.
resource
.
toString
()
===
fileResource
.
toString
())[
0
];
return
this
.
textModelResolverService
.
createModelReference
(
fileResource
).
then
(
ref
=>
{
ref
=
this
.
_register
(
ref
);
const
ref
=
this
.
_register
(
await
this
.
textModelResolverService
.
createModelReference
(
fileResource
));
const
sourceModel
=
ref
.
object
.
textEditorModel
;
const
sourceModelModeId
=
sourceModel
.
getLanguageIdentifier
().
language
;
const
replacePreviewModel
=
this
.
modelService
.
createModel
(
createTextBufferFactoryFromSnapshot
(
sourceModel
.
createSnapshot
()),
this
.
modeService
.
create
(
sourceModelModeId
),
replacePreviewUri
);
...
...
@@ -79,7 +77,6 @@ class ReplacePreviewModel extends Disposable {
this
.
_register
(
replacePreviewModel
.
onWillDispose
(()
=>
this
.
dispose
()));
this
.
_register
(
sourceModel
.
onWillDispose
(()
=>
this
.
dispose
()));
return
replacePreviewModel
;
});
}
private
update
(
sourceModel
:
ITextModel
,
replacePreviewModel
:
ITextModel
,
fileMatch
:
FileMatch
,
override
:
boolean
=
false
):
void
{
...
...
@@ -103,15 +100,24 @@ export class ReplaceService implements IReplaceService {
replace
(
match
:
Match
):
Promise
<
any
>
;
replace
(
files
:
FileMatch
[],
progress
?:
IProgress
<
IProgressStep
>
):
Promise
<
any
>
;
replace
(
match
:
FileMatchOrMatch
,
progress
?:
IProgress
<
IProgressStep
>
,
resource
?:
URI
):
Promise
<
any
>
;
replace
(
arg
:
any
,
progress
:
IProgress
<
IProgressStep
>
|
undefined
=
undefined
,
resource
:
URI
|
null
=
null
):
Promise
<
any
>
{
async
replace
(
arg
:
any
,
progress
:
IProgress
<
IProgressStep
>
|
undefined
=
undefined
,
resource
:
URI
|
null
=
null
):
Promise
<
any
>
{
const
edits
:
ResourceTextEdit
[]
=
this
.
createEdits
(
arg
,
resource
);
return
this
.
bulkEditorService
.
apply
({
edits
},
{
progress
}).
then
(()
=>
this
.
textFileService
.
saveAll
(
edits
.
map
(
e
=>
e
.
resource
)));
await
this
.
bulkEditorService
.
apply
({
edits
},
{
progress
});
return
Promise
.
all
(
edits
.
map
(
e
=>
{
const
model
=
this
.
textFileService
.
models
.
get
(
e
.
resource
);
if
(
model
)
{
return
model
.
save
();
}
return
Promise
.
resolve
(
undefined
);
}));
}
openReplacePreview
(
element
:
FileMatchOrMatch
,
preserveFocus
?:
boolean
,
sideBySide
?:
boolean
,
pinned
?:
boolean
):
Promise
<
any
>
{
async
openReplacePreview
(
element
:
FileMatchOrMatch
,
preserveFocus
?:
boolean
,
sideBySide
?:
boolean
,
pinned
?:
boolean
):
Promise
<
any
>
{
const
fileMatch
=
element
instanceof
Match
?
element
.
parent
()
:
element
;
return
this
.
editorService
.
openEditor
({
const
editor
=
await
this
.
editorService
.
openEditor
({
leftResource
:
fileMatch
.
resource
,
rightResource
:
toReplaceResource
(
fileMatch
.
resource
),
label
:
nls
.
localize
(
'
fileReplaceChanges
'
,
"
{0} ↔ {1} (Replace Preview)
"
,
fileMatch
.
name
(),
fileMatch
.
name
()),
...
...
@@ -120,7 +126,7 @@ export class ReplaceService implements IReplaceService {
pinned
,
revealIfVisible
:
true
}
})
.
then
(
editor
=>
{
})
;
const
input
=
editor
?.
input
;
const
disposable
=
fileMatch
.
onDispose
(()
=>
{
if
(
input
)
{
...
...
@@ -128,24 +134,20 @@ export class ReplaceService implements IReplaceService {
}
disposable
.
dispose
();
});
this
.
updateReplacePreview
(
fileMatch
).
then
(()
=>
{
await
this
.
updateReplacePreview
(
fileMatch
);
if
(
editor
)
{
const
editorControl
=
editor
.
getControl
();
if
(
element
instanceof
Match
&&
editorControl
)
{
editorControl
.
revealLineInCenter
(
element
.
range
().
startLineNumber
,
ScrollType
.
Immediate
);
}
}
});
},
errors
.
onUnexpectedError
);
}
updateReplacePreview
(
fileMatch
:
FileMatch
,
override
:
boolean
=
false
):
Promise
<
void
>
{
async
updateReplacePreview
(
fileMatch
:
FileMatch
,
override
:
boolean
=
false
):
Promise
<
void
>
{
const
replacePreviewUri
=
toReplaceResource
(
fileMatch
.
resource
);
return
Promise
.
all
([
this
.
textModelResolverService
.
createModelReference
(
fileMatch
.
resource
),
this
.
textModelResolverService
.
createModelReference
(
replacePreviewUri
)])
.
then
(([
sourceModelRef
,
replaceModelRef
])
=>
{
const
[
sourceModelRef
,
replaceModelRef
]
=
await
Promise
.
all
([
this
.
textModelResolverService
.
createModelReference
(
fileMatch
.
resource
),
this
.
textModelResolverService
.
createModelReference
(
replacePreviewUri
)]);
const
sourceModel
=
sourceModelRef
.
object
.
textEditorModel
;
const
replaceModel
=
replaceModelRef
.
object
.
textEditorModel
;
const
returnValue
=
Promise
.
resolve
(
null
);
// If model is disposed do not update
if
(
sourceModel
&&
replaceModel
)
{
if
(
override
)
{
...
...
@@ -155,11 +157,8 @@ export class ReplaceService implements IReplaceService {
}
this
.
applyEditsToPreview
(
fileMatch
,
replaceModel
);
}
return
returnValue
.
then
(()
=>
{
sourceModelRef
.
dispose
();
replaceModelRef
.
dispose
();
});
});
}
private
applyEditsToPreview
(
fileMatch
:
FileMatch
,
replaceModel
:
ITextModel
):
void
{
...
...
src/vs/workbench/services/configuration/common/configurationEditingService.ts
浏览文件 @
9b6ae0ca
...
...
@@ -487,7 +487,7 @@ export class ConfigurationEditingService {
}
// Target cannot be dirty if not writing into buffer
if
(
checkDirty
&&
this
.
textFileService
.
isDirty
(
operation
.
resource
))
{
if
(
checkDirty
&&
operation
.
resource
&&
this
.
textFileService
.
isDirty
(
operation
.
resource
))
{
return
this
.
reject
<
typeof
reference
>
(
ConfigurationEditingErrorCode
.
ERROR_CONFIGURATION_FILE_DIRTY
,
target
,
operation
);
}
return
reference
;
...
...
src/vs/workbench/services/textfile/browser/textFileService.ts
浏览文件 @
9b6ae0ca
...
...
@@ -177,7 +177,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
await
this
.
_onWillRunOperation
.
fireAsync
({
operation
:
FileOperation
.
DELETE
,
target
:
resource
},
CancellationToken
.
None
);
const
dirtyFiles
=
this
.
getDirty
().
filter
(
dirty
=>
isEqualOrParent
(
dirty
,
resource
));
await
this
.
r
evertAll
(
dirtyFiles
,
{
soft
:
true
});
await
this
.
doR
evertAll
(
dirtyFiles
,
{
soft
:
true
});
await
this
.
fileService
.
del
(
resource
,
options
);
...
...
@@ -243,7 +243,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
// in order to move and copy, we need to soft revert all dirty models,
// both from the source as well as the target if any
const
dirtyModels
=
[...
sourceModels
,
...
conflictingModels
].
filter
(
model
=>
model
.
isDirty
());
await
this
.
r
evertAll
(
dirtyModels
.
map
(
dirtyModel
=>
dirtyModel
.
resource
),
{
soft
:
true
});
await
this
.
doR
evertAll
(
dirtyModels
.
map
(
dirtyModel
=>
dirtyModel
.
resource
),
{
soft
:
true
});
// now we can rename the source to target via file operation
let
stat
:
IFileStatWithMetadata
;
...
...
@@ -290,85 +290,44 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
//#region save
async
save
(
resource
:
URI
,
options
?:
ITextFileSaveOptions
):
Promise
<
boolean
>
{
return
!
(
await
this
.
saveAll
([
resource
],
options
)).
results
.
some
(
result
=>
result
.
error
);
}
saveAll
(
includeUntitled
?:
boolean
,
options
?:
ITextFileSaveOptions
):
Promise
<
ITextFileOperationResult
>
;
saveAll
(
resources
:
URI
[],
options
?:
ITextFileSaveOptions
):
Promise
<
ITextFileOperationResult
>
;
saveAll
(
arg1
?:
boolean
|
URI
[],
options
?:
ITextFileSaveOptions
):
Promise
<
ITextFileOperationResult
>
{
// Extract the resources to save
let
resourcesToSave
:
URI
[]
=
[];
if
(
Array
.
isArray
(
arg1
))
{
// if specific resources are given, we consider even
// non-dirty ones if options.force is provided
if
(
options
?.
force
)
{
resourcesToSave
=
arg1
;
}
else
{
resourcesToSave
=
this
.
getDirty
(
arg1
);
}
}
else
{
// if no resources are given, we only consider dirty
// resources even if options.force is provided
resourcesToSave
=
this
.
getDirty
();
}
// split up between files and untitled
const
filesToSave
:
URI
[]
=
[];
const
untitledToSave
:
URI
[]
=
[];
resourcesToSave
.
forEach
(
resourceToSave
=>
{
if
((
Array
.
isArray
(
arg1
)
||
arg1
===
true
/* includeUntitled */
)
&&
resourceToSave
.
scheme
===
Schemas
.
untitled
)
{
untitledToSave
.
push
(
resourceToSave
);
}
else
if
(
this
.
fileService
.
canHandleResource
(
resourceToSave
))
{
filesToSave
.
push
(
resourceToSave
);
}
});
return
this
.
doSaveAll
(
filesToSave
,
untitledToSave
,
options
);
}
private
async
doSaveAll
(
fileResources
:
URI
[],
untitledResources
:
URI
[],
options
?:
ITextFileSaveOptions
):
Promise
<
ITextFileOperationResult
>
{
// Handle files first that can just be saved
const
result
=
await
this
.
doSaveAllFiles
(
fileResources
,
options
);
// Preflight for untitled to handle cancellation from the dialog
const
targetsForUntitled
:
URI
[]
=
[];
for
(
const
untitled
of
untitledResources
)
{
if
(
this
.
untitledTextEditorService
.
exists
(
untitled
))
{
let
targetUri
:
URI
;
// Untitled
if
(
resource
.
scheme
===
Schemas
.
untitled
)
{
if
(
this
.
untitledTextEditorService
.
exists
(
resource
))
{
let
targetUri
:
URI
|
undefined
;
// Untitled with associated file path don't need to prompt
if
(
this
.
untitledTextEditorService
.
hasAssociatedFilePath
(
untitled
))
{
targetUri
=
toLocalResource
(
untitled
,
this
.
environmentService
.
configuration
.
remoteAuthority
);
if
(
this
.
untitledTextEditorService
.
hasAssociatedFilePath
(
resource
))
{
targetUri
=
toLocalResource
(
resource
,
this
.
environmentService
.
configuration
.
remoteAuthority
);
}
// Otherwise ask user
else
{
const
targetPath
=
await
this
.
promptForPath
(
untitled
,
this
.
suggestFileName
(
untitled
));
if
(
!
targetPath
)
{
return
{
results
:
[...
fileResources
,
...
untitledResources
].
map
(
r
=>
({
source
:
r
}))
};
targetUri
=
await
this
.
promptForPath
(
resource
,
this
.
suggestFileName
(
resource
));
}
targetUri
=
targetPath
;
}
// Save as if target provided
if
(
targetUri
)
{
await
this
.
saveAs
(
resource
,
targetUri
,
options
);
targetsForUntitled
.
push
(
targetUri
);
return
true
;
}
}
}
// Handle untitled
await
Promise
.
all
(
targetsForUntitled
.
map
(
async
(
target
,
index
)
=>
{
const
uri
=
await
this
.
saveAs
(
untitledResources
[
index
],
target
);
// File
else
{
const
model
=
this
.
models
.
get
(
resource
);
if
(
model
)
{
result
.
results
.
push
({
source
:
untitledResources
[
index
],
target
:
uri
,
error
:
!
uri
// the operation was canceled or failed, so mark as error
});
}));
// Save with options
await
model
.
save
(
options
);
return
result
;
return
!
model
.
isDirty
();
}
}
return
false
;
}
protected
async
promptForPath
(
resource
:
URI
,
defaultUri
:
URI
,
availableFileSystems
?:
readonly
string
[]):
Promise
<
URI
|
undefined
>
{
...
...
@@ -432,32 +391,6 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
return
options
;
}
private
async
doSaveAllFiles
(
resources
?:
URI
[],
options
:
ITextFileSaveOptions
=
Object
.
create
(
null
)):
Promise
<
ITextFileOperationResult
>
{
const
fileModelsToSave
=
this
.
getFileModels
(
resources
);
const
mapResourceToResult
=
new
ResourceMap
<
IResult
>
();
for
(
const
fileModelToSave
of
fileModelsToSave
)
{
mapResourceToResult
.
set
(
fileModelToSave
.
resource
,
{
source
:
fileModelToSave
.
resource
});
}
// Save all in parallel
await
Promise
.
all
(
fileModelsToSave
.
map
(
async
model
=>
{
// Save with options
await
model
.
save
(
options
);
// If model is still dirty, mark the resulting operation as error
if
(
model
.
isDirty
())
{
const
result
=
mapResourceToResult
.
get
(
model
.
resource
);
if
(
result
)
{
result
.
error
=
true
;
}
}
}));
return
{
results
:
mapResourceToResult
.
values
()
};
}
private
getFileModels
(
arg1
?:
URI
|
URI
[]):
ITextFileEditorModel
[]
{
if
(
Array
.
isArray
(
arg1
))
{
const
models
:
ITextFileEditorModel
[]
=
[];
...
...
@@ -682,10 +615,10 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
//#region revert
async
revert
(
resource
:
URI
,
options
?:
IRevertOptions
):
Promise
<
boolean
>
{
return
!
(
await
this
.
r
evertAll
([
resource
],
options
)).
results
.
some
(
result
=>
result
.
error
);
return
!
(
await
this
.
doR
evertAll
([
resource
],
options
)).
results
.
some
(
result
=>
result
.
error
);
}
async
r
evertAll
(
resources
?:
URI
[],
options
?:
IRevertOptions
):
Promise
<
ITextFileOperationResult
>
{
private
async
doR
evertAll
(
resources
?:
URI
[],
options
?:
IRevertOptions
):
Promise
<
ITextFileOperationResult
>
{
// Revert files first
const
revertOperationResult
=
await
this
.
doRevertAllFiles
(
resources
,
options
);
...
...
@@ -739,18 +672,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
//#region dirty
getDirty
(
resources
?:
URI
[]):
URI
[]
{
// Collect files
const
dirty
=
this
.
getDirtyFileModels
(
resources
).
map
(
dirtyFileModel
=>
dirtyFileModel
.
resource
);
// Add untitled ones
dirty
.
push
(...
this
.
untitledTextEditorService
.
getDirty
(
resources
));
return
dirty
;
}
isDirty
(
resource
?:
URI
):
boolean
{
isDirty
(
resource
:
URI
):
boolean
{
// Check for dirty file
if
(
this
.
models
.
getAll
(
resource
).
some
(
model
=>
model
.
isDirty
()))
{
...
...
@@ -761,5 +683,16 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
return
this
.
untitledTextEditorService
.
getDirty
().
some
(
dirty
=>
!
resource
||
dirty
.
toString
()
===
resource
.
toString
());
}
protected
getDirty
(
resources
?:
URI
[]):
URI
[]
{
// Collect files
const
dirty
=
this
.
getDirtyFileModels
(
resources
).
map
(
dirtyFileModel
=>
dirtyFileModel
.
resource
);
// Add untitled ones
dirty
.
push
(...
this
.
untitledTextEditorService
.
getDirty
(
resources
));
return
dirty
;
}
//#endregion
}
src/vs/workbench/services/textfile/common/textfiles.ts
浏览文件 @
9b6ae0ca
...
...
@@ -45,18 +45,9 @@ export interface ITextFileService extends IDisposable {
/**
* A resource is dirty if it has unsaved changes or is an untitled file not yet saved.
*
* @param resource the resource to check for being dirty. If it is not specified, will check for
* all dirty resources.
* @param resource the resource to check for being dirty
*/
isDirty
(
resource
?:
URI
):
boolean
;
/**
* Returns all resources that are currently dirty matching the provided resources or all dirty resources.
*
* @param resources the resources to check for being dirty. If it is not specified, will check for
* all dirty resources.
*/
getDirty
(
resources
?:
URI
[]):
URI
[];
isDirty
(
resource
:
URI
):
boolean
;
/**
* Saves the resource.
...
...
@@ -77,15 +68,6 @@ export interface ITextFileService extends IDisposable {
*/
saveAs
(
resource
:
URI
,
targetResource
?:
URI
,
options
?:
ISaveOptions
):
Promise
<
URI
|
undefined
>
;
/**
* Saves the set of resources and returns a promise with the operation result.
*
* @param resources can be null to save all.
* @param includeUntitled to save all resources and optionally exclude untitled ones.
*/
saveAll
(
includeUntitled
?:
boolean
,
options
?:
ISaveOptions
):
Promise
<
ITextFileOperationResult
>
;
saveAll
(
resources
:
URI
[],
options
?:
ISaveOptions
):
Promise
<
ITextFileOperationResult
>
;
/**
* Reverts the provided resource.
*
...
...
@@ -94,11 +76,6 @@ export interface ITextFileService extends IDisposable {
*/
revert
(
resource
:
URI
,
options
?:
IRevertOptions
):
Promise
<
boolean
>
;
/**
* Reverts all the provided resources and returns a promise with the operation result.
*/
revertAll
(
resources
?:
URI
[],
options
?:
IRevertOptions
):
Promise
<
ITextFileOperationResult
>
;
/**
* Create a file. If the file exists it will be overwritten with the contents if
* the options enable to overwrite.
...
...
src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts
浏览文件 @
9b6ae0ca
...
...
@@ -386,7 +386,6 @@ suite('Files - TextFileEditorModel', () => {
assert
.
ok
(
m1Mtime
>
0
);
assert
.
ok
(
m2Mtime
>
0
);
assert
.
ok
(
accessor
.
textFileService
.
isDirty
());
assert
.
ok
(
accessor
.
textFileService
.
isDirty
(
toResource
.
call
(
this
,
'
/path/index_async2.txt
'
)));
assert
.
ok
(
!
accessor
.
textFileService
.
isDirty
(
toResource
.
call
(
this
,
'
/path/index_async.txt
'
)));
...
...
@@ -394,7 +393,8 @@ suite('Files - TextFileEditorModel', () => {
assert
.
ok
(
accessor
.
textFileService
.
isDirty
(
toResource
.
call
(
this
,
'
/path/index_async.txt
'
)));
await
timeout
(
10
);
await
accessor
.
textFileService
.
saveAll
();
await
accessor
.
textFileService
.
save
(
toResource
.
call
(
this
,
'
/path/index_async.txt
'
));
await
accessor
.
textFileService
.
save
(
toResource
.
call
(
this
,
'
/path/index_async2.txt
'
));
assert
.
ok
(
!
accessor
.
textFileService
.
isDirty
(
toResource
.
call
(
this
,
'
/path/index_async.txt
'
)));
assert
.
ok
(
!
accessor
.
textFileService
.
isDirty
(
toResource
.
call
(
this
,
'
/path/index_async2.txt
'
)));
assert
.
ok
(
assertIsDefined
(
model1
.
getStat
()).
mtime
>
m1Mtime
);
...
...
src/vs/workbench/services/textfile/test/textFileService.test.ts
浏览文件 @
9b6ae0ca
...
...
@@ -60,42 +60,38 @@ suite('Files - TextFileService', () => {
model
=
instantiationService
.
createInstance
(
TextFileEditorModel
,
toResource
.
call
(
this
,
'
/path/file.txt
'
),
'
utf8
'
,
undefined
);
(
<
TextFileEditorModelManager
>
accessor
.
textFileService
.
models
).
add
(
model
.
resource
,
model
);
const
service
=
accessor
.
textFileService
;
await
model
.
load
();
assert
.
ok
(
!
s
ervice
.
isDirty
(
model
.
resource
));
assert
.
ok
(
!
accessor
.
textFileS
ervice
.
isDirty
(
model
.
resource
));
model
.
textEditorModel
!
.
setValue
(
'
foo
'
);
assert
.
ok
(
s
ervice
.
isDirty
(
model
.
resource
));
assert
.
equal
(
s
ervice
.
getDirty
().
length
,
1
);
assert
.
equal
(
s
ervice
.
getDirty
([
model
.
resource
])[
0
].
toString
(),
model
.
resource
.
toString
());
assert
.
ok
(
accessor
.
textFileS
ervice
.
isDirty
(
model
.
resource
));
assert
.
equal
(
accessor
.
textFileS
ervice
.
getDirty
().
length
,
1
);
assert
.
equal
(
accessor
.
textFileS
ervice
.
getDirty
([
model
.
resource
])[
0
].
toString
(),
model
.
resource
.
toString
());
const
untitled
=
accessor
.
untitledTextEditorService
.
createOrGet
();
const
untitledModel
=
await
untitled
.
resolve
();
assert
.
ok
(
!
s
ervice
.
isDirty
(
untitled
.
getResource
()));
assert
.
equal
(
s
ervice
.
getDirty
().
length
,
1
);
assert
.
ok
(
!
accessor
.
textFileS
ervice
.
isDirty
(
untitled
.
getResource
()));
assert
.
equal
(
accessor
.
textFileS
ervice
.
getDirty
().
length
,
1
);
untitledModel
.
textEditorModel
!
.
setValue
(
'
changed
'
);
assert
.
ok
(
s
ervice
.
isDirty
(
untitled
.
getResource
()));
assert
.
equal
(
s
ervice
.
getDirty
().
length
,
2
);
assert
.
equal
(
s
ervice
.
getDirty
([
untitled
.
getResource
()])[
0
].
toString
(),
untitled
.
getResource
().
toString
());
assert
.
ok
(
accessor
.
textFileS
ervice
.
isDirty
(
untitled
.
getResource
()));
assert
.
equal
(
accessor
.
textFileS
ervice
.
getDirty
().
length
,
2
);
assert
.
equal
(
accessor
.
textFileS
ervice
.
getDirty
([
untitled
.
getResource
()])[
0
].
toString
(),
untitled
.
getResource
().
toString
());
});
test
(
'
save - file
'
,
async
function
()
{
model
=
instantiationService
.
createInstance
(
TextFileEditorModel
,
toResource
.
call
(
this
,
'
/path/file.txt
'
),
'
utf8
'
,
undefined
);
(
<
TextFileEditorModelManager
>
accessor
.
textFileService
.
models
).
add
(
model
.
resource
,
model
);
const
service
=
accessor
.
textFileService
;
await
model
.
load
();
model
.
textEditorModel
!
.
setValue
(
'
foo
'
);
assert
.
ok
(
s
ervice
.
isDirty
(
model
.
resource
));
assert
.
ok
(
accessor
.
textFileS
ervice
.
isDirty
(
model
.
resource
));
const
res
=
await
s
ervice
.
save
(
model
.
resource
);
const
res
=
await
accessor
.
textFileS
ervice
.
save
(
model
.
resource
);
assert
.
ok
(
res
);
assert
.
ok
(
!
s
ervice
.
isDirty
(
model
.
resource
));
assert
.
ok
(
!
accessor
.
textFileS
ervice
.
isDirty
(
model
.
resource
));
});
test
(
'
save - UNC path
'
,
async
function
()
{
...
...
@@ -114,76 +110,62 @@ suite('Files - TextFileService', () => {
await
model
.
load
();
model
.
textEditorModel
!
.
setValue
(
'
foo
'
);
const
res
=
await
accessor
.
textFileService
.
save
All
(
true
);
const
res
=
await
accessor
.
textFileService
.
save
(
untitledUncUri
);
assert
.
ok
(
loadOrCreateStub
.
calledOnce
);
assert
.
equal
(
res
.
results
.
length
,
1
);
assert
.
ok
(
!
res
.
results
[
0
].
error
);
assert
.
equal
(
res
.
results
[
0
].
target
!
.
scheme
,
Schemas
.
file
);
assert
.
equal
(
res
.
results
[
0
].
target
!
.
authority
,
untitledUncUri
.
authority
);
assert
.
equal
(
res
.
results
[
0
].
target
!
.
path
,
untitledUncUri
.
path
);
assert
.
ok
(
res
);
});
test
(
'
saveAll - file
'
,
async
function
()
{
model
=
instantiationService
.
createInstance
(
TextFileEditorModel
,
toResource
.
call
(
this
,
'
/path/file.txt
'
),
'
utf8
'
,
undefined
);
(
<
TextFileEditorModelManager
>
accessor
.
textFileService
.
models
).
add
(
model
.
resource
,
model
);
const
service
=
accessor
.
textFileService
;
await
model
.
load
();
model
.
textEditorModel
!
.
setValue
(
'
foo
'
);
assert
.
ok
(
s
ervice
.
isDirty
(
model
.
resource
));
assert
.
ok
(
accessor
.
textFileS
ervice
.
isDirty
(
model
.
resource
));
const
res
=
await
service
.
saveAll
([
model
.
resource
]
);
const
res
=
await
accessor
.
textFileService
.
save
(
model
.
resource
);
assert
.
ok
(
res
);
assert
.
ok
(
!
service
.
isDirty
(
model
.
resource
));
assert
.
equal
(
res
.
results
.
length
,
1
);
assert
.
equal
(
res
.
results
[
0
].
source
.
toString
(),
model
.
resource
.
toString
());
assert
.
ok
(
!
accessor
.
textFileService
.
isDirty
(
model
.
resource
));
});
test
(
'
saveAs - file
'
,
async
function
()
{
model
=
instantiationService
.
createInstance
(
TextFileEditorModel
,
toResource
.
call
(
this
,
'
/path/file.txt
'
),
'
utf8
'
,
undefined
);
(
<
TextFileEditorModelManager
>
accessor
.
textFileService
.
models
).
add
(
model
.
resource
,
model
);
const
service
=
accessor
.
textFileService
;
service
.
setPromptPath
(
model
.
resource
);
accessor
.
textFileService
.
setPromptPath
(
model
.
resource
);
await
model
.
load
();
model
.
textEditorModel
!
.
setValue
(
'
foo
'
);
assert
.
ok
(
s
ervice
.
isDirty
(
model
.
resource
));
assert
.
ok
(
accessor
.
textFileS
ervice
.
isDirty
(
model
.
resource
));
const
res
=
await
s
ervice
.
saveAs
(
model
.
resource
);
const
res
=
await
accessor
.
textFileS
ervice
.
saveAs
(
model
.
resource
);
assert
.
equal
(
res
!
.
toString
(),
model
.
resource
.
toString
());
assert
.
ok
(
!
s
ervice
.
isDirty
(
model
.
resource
));
assert
.
ok
(
!
accessor
.
textFileS
ervice
.
isDirty
(
model
.
resource
));
});
test
(
'
revert - file
'
,
async
function
()
{
model
=
instantiationService
.
createInstance
(
TextFileEditorModel
,
toResource
.
call
(
this
,
'
/path/file.txt
'
),
'
utf8
'
,
undefined
);
(
<
TextFileEditorModelManager
>
accessor
.
textFileService
.
models
).
add
(
model
.
resource
,
model
);
const
service
=
accessor
.
textFileService
;
service
.
setPromptPath
(
model
.
resource
);
accessor
.
textFileService
.
setPromptPath
(
model
.
resource
);
await
model
.
load
();
model
!
.
textEditorModel
!
.
setValue
(
'
foo
'
);
assert
.
ok
(
s
ervice
.
isDirty
(
model
.
resource
));
assert
.
ok
(
accessor
.
textFileS
ervice
.
isDirty
(
model
.
resource
));
const
res
=
await
s
ervice
.
revert
(
model
.
resource
);
const
res
=
await
accessor
.
textFileS
ervice
.
revert
(
model
.
resource
);
assert
.
ok
(
res
);
assert
.
ok
(
!
s
ervice
.
isDirty
(
model
.
resource
));
assert
.
ok
(
!
accessor
.
textFileS
ervice
.
isDirty
(
model
.
resource
));
});
test
(
'
delete - dirty file
'
,
async
function
()
{
model
=
instantiationService
.
createInstance
(
TextFileEditorModel
,
toResource
.
call
(
this
,
'
/path/file.txt
'
),
'
utf8
'
,
undefined
);
(
<
TextFileEditorModelManager
>
accessor
.
textFileService
.
models
).
add
(
model
.
resource
,
model
);
const
service
=
accessor
.
textFileService
;
await
model
.
load
();
model
!
.
textEditorModel
!
.
setValue
(
'
foo
'
);
assert
.
ok
(
s
ervice
.
isDirty
(
model
.
resource
));
assert
.
ok
(
accessor
.
textFileS
ervice
.
isDirty
(
model
.
resource
));
await
s
ervice
.
delete
(
model
.
resource
);
assert
.
ok
(
!
s
ervice
.
isDirty
(
model
.
resource
));
await
accessor
.
textFileS
ervice
.
delete
(
model
.
resource
);
assert
.
ok
(
!
accessor
.
textFileS
ervice
.
isDirty
(
model
.
resource
));
});
test
(
'
move - dirty file
'
,
async
function
()
{
...
...
@@ -200,24 +182,22 @@ suite('Files - TextFileService', () => {
(
<
TextFileEditorModelManager
>
accessor
.
textFileService
.
models
).
add
(
sourceModel
.
resource
,
sourceModel
);
(
<
TextFileEditorModelManager
>
accessor
.
textFileService
.
models
).
add
(
targetModel
.
resource
,
targetModel
);
const
service
=
accessor
.
textFileService
;
await
sourceModel
.
load
();
sourceModel
.
textEditorModel
!
.
setValue
(
'
foo
'
);
assert
.
ok
(
s
ervice
.
isDirty
(
sourceModel
.
resource
));
assert
.
ok
(
accessor
.
textFileS
ervice
.
isDirty
(
sourceModel
.
resource
));
if
(
targetDirty
)
{
await
targetModel
.
load
();
targetModel
.
textEditorModel
!
.
setValue
(
'
bar
'
);
assert
.
ok
(
s
ervice
.
isDirty
(
targetModel
.
resource
));
assert
.
ok
(
accessor
.
textFileS
ervice
.
isDirty
(
targetModel
.
resource
));
}
await
s
ervice
.
move
(
sourceModel
.
resource
,
targetModel
.
resource
,
true
);
await
accessor
.
textFileS
ervice
.
move
(
sourceModel
.
resource
,
targetModel
.
resource
,
true
);
assert
.
equal
(
targetModel
.
textEditorModel
!
.
getValue
(),
'
foo
'
);
assert
.
ok
(
!
s
ervice
.
isDirty
(
sourceModel
.
resource
));
assert
.
ok
(
s
ervice
.
isDirty
(
targetModel
.
resource
));
assert
.
ok
(
!
accessor
.
textFileS
ervice
.
isDirty
(
sourceModel
.
resource
));
assert
.
ok
(
accessor
.
textFileS
ervice
.
isDirty
(
targetModel
.
resource
));
sourceModel
.
dispose
();
targetModel
.
dispose
();
...
...
src/vs/workbench/services/workingCopy/common/workingCopyService.ts
浏览文件 @
9b6ae0ca
...
...
@@ -94,6 +94,8 @@ export interface IWorkingCopyService {
readonly
workingCopies
:
IWorkingCopy
[];
getWorkingCopies
(
resource
:
URI
):
IWorkingCopy
[];
registerWorkingCopy
(
workingCopy
:
IWorkingCopy
):
IDisposable
;
//#endregion
...
...
@@ -127,6 +129,12 @@ export class WorkingCopyService extends Disposable implements IWorkingCopyServic
get
workingCopies
():
IWorkingCopy
[]
{
return
values
(
this
.
_workingCopies
);
}
private
_workingCopies
=
new
Set
<
IWorkingCopy
>
();
getWorkingCopies
(
resource
:
URI
):
IWorkingCopy
[]
{
const
workingCopies
=
this
.
mapResourceToWorkingCopy
.
get
(
resource
.
toString
());
return
workingCopies
?
values
(
workingCopies
)
:
[];
}
registerWorkingCopy
(
workingCopy
:
IWorkingCopy
):
IDisposable
{
const
disposables
=
new
DisposableStore
();
...
...
src/vs/workbench/services/workingCopy/test/common/workingCopyService.test.ts
浏览文件 @
9b6ae0ca
...
...
@@ -109,6 +109,8 @@ suite('WorkingCopyService', () => {
assert
.
equal
(
service
.
dirtyCount
,
1
);
assert
.
equal
(
service
.
dirtyWorkingCopies
.
length
,
1
);
assert
.
equal
(
service
.
dirtyWorkingCopies
[
0
],
copy1
);
assert
.
equal
(
service
.
getWorkingCopies
(
copy1
.
resource
).
length
,
1
);
assert
.
equal
(
service
.
getWorkingCopies
(
copy1
.
resource
)[
0
],
copy1
);
assert
.
equal
(
service
.
isDirty
(
resource1
),
true
);
assert
.
equal
(
service
.
hasDirty
,
true
);
assert
.
equal
(
onDidChangeDirty
.
length
,
1
);
...
...
@@ -176,6 +178,10 @@ suite('WorkingCopyService', () => {
const
copy2
=
new
TestWorkingCopy
(
resource
);
const
unregister2
=
service
.
registerWorkingCopy
(
copy2
);
assert
.
equal
(
service
.
getWorkingCopies
(
copy1
.
resource
).
length
,
2
);
assert
.
equal
(
service
.
getWorkingCopies
(
copy1
.
resource
)[
0
],
copy1
);
assert
.
equal
(
service
.
getWorkingCopies
(
copy1
.
resource
)[
1
],
copy2
);
copy1
.
setDirty
(
true
);
assert
.
equal
(
service
.
dirtyCount
,
1
);
...
...
src/vs/workbench/test/workbenchTestServices.ts
浏览文件 @
9b6ae0ca
...
...
@@ -261,6 +261,10 @@ export class TestTextFileService extends NativeTextFileService {
promptForPath
(
_resource
:
URI
,
_defaultPath
:
URI
):
Promise
<
URI
>
{
return
Promise
.
resolve
(
this
.
promptPath
);
}
getDirty
(
resources
?:
URI
[]):
URI
[]
{
return
super
.
getDirty
(
resources
);
}
}
export
interface
ITestInstantiationService
extends
IInstantiationService
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录