Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
497ea886
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,发现更多精彩内容 >>
提交
497ea886
编写于
9月 03, 2018
作者:
R
Rob Lourens
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
#56137 - remove more TPromise#cancel from search
上级
5f513e74
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
175 addition
and
156 deletion
+175
-156
src/vs/platform/search/common/search.ts
src/vs/platform/search/common/search.ts
+3
-2
src/vs/workbench/api/electron-browser/mainThreadSearch.ts
src/vs/workbench/api/electron-browser/mainThreadSearch.ts
+16
-21
src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts
src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts
+30
-19
src/vs/workbench/api/node/extHostSearch.ts
src/vs/workbench/api/node/extHostSearch.ts
+23
-36
src/vs/workbench/parts/search/browser/openFileHandler.ts
src/vs/workbench/parts/search/browser/openFileHandler.ts
+1
-2
src/vs/workbench/parts/search/common/searchModel.ts
src/vs/workbench/parts/search/common/searchModel.ts
+11
-11
src/vs/workbench/parts/search/test/common/searchModel.test.ts
...vs/workbench/parts/search/test/common/searchModel.test.ts
+23
-6
src/vs/workbench/services/search/node/searchService.ts
src/vs/workbench/services/search/node/searchService.ts
+68
-59
未找到文件。
src/vs/platform/search/common/search.ts
浏览文件 @
497ea886
...
...
@@ -13,6 +13,7 @@ import { URI as uri, UriComponents } from 'vs/base/common/uri';
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IFilesConfiguration
}
from
'
vs/platform/files/common/files
'
;
import
{
createDecorator
}
from
'
vs/platform/instantiation/common/instantiation
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
export
const
VIEW_ID
=
'
workbench.view.search
'
;
...
...
@@ -24,7 +25,7 @@ export const ISearchService = createDecorator<ISearchService>('searchService');
*/
export
interface
ISearchService
{
_serviceBrand
:
any
;
search
(
query
:
ISearchQuery
,
onProgress
?:
(
result
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
;
search
(
query
:
ISearchQuery
,
token
?:
CancellationToken
,
onProgress
?:
(
result
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
;
extendQuery
(
query
:
ISearchQuery
):
void
;
clearCache
(
cacheKey
:
string
):
TPromise
<
void
>
;
registerSearchResultProvider
(
scheme
:
string
,
type
:
SearchProviderType
,
provider
:
ISearchResultProvider
):
IDisposable
;
...
...
@@ -55,7 +56,7 @@ export enum SearchProviderType {
}
export
interface
ISearchResultProvider
{
search
(
query
:
ISearchQuery
,
onProgress
?:
(
p
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
;
search
(
query
:
ISearchQuery
,
onProgress
?:
(
p
:
ISearchProgressItem
)
=>
void
,
token
?:
CancellationToken
):
TPromise
<
ISearchComplete
>
;
clearCache
(
cacheKey
:
string
):
TPromise
<
void
>
;
}
...
...
src/vs/workbench/api/electron-browser/mainThreadSearch.ts
浏览文件 @
497ea886
...
...
@@ -13,6 +13,7 @@ import { IFileMatch, IRawFileMatch2, ISearchComplete, ISearchCompleteStats, ISea
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
extHostNamedCustomer
}
from
'
vs/workbench/api/electron-browser/extHostCustomers
'
;
import
{
ExtHostContext
,
ExtHostSearchShape
,
IExtHostContext
,
MainContext
,
MainThreadSearchShape
}
from
'
../node/extHost.protocol
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
@
extHostNamedCustomer
(
MainContext
.
MainThreadSearch
)
export
class
MainThreadSearch
implements
MainThreadSearchShape
{
...
...
@@ -106,34 +107,28 @@ class RemoteSearchProvider implements ISearchResultProvider, IDisposable {
dispose
(
this
.
_registrations
);
}
search
(
query
:
ISearchQuery
,
onProgress
?:
(
p
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
{
search
(
query
:
ISearchQuery
,
onProgress
?:
(
p
:
ISearchProgressItem
)
=>
void
,
token
?:
CancellationToken
):
TPromise
<
ISearchComplete
>
{
if
(
isFalsyOrEmpty
(
query
.
folderQueries
))
{
return
TPromise
.
as
(
undefined
);
}
let
outer
:
TPromise
;
return
new
TPromise
((
resolve
,
reject
)
=>
{
const
search
=
new
SearchOperation
(
onProgress
);
this
.
_searches
.
set
(
search
.
id
,
search
);
const
search
=
new
SearchOperation
(
onProgress
);
this
.
_searches
.
set
(
search
.
id
,
search
);
const
searchP
=
query
.
type
===
QueryType
.
File
?
this
.
_proxy
.
$provideFileSearchResults
(
this
.
_handle
,
search
.
id
,
query
)
:
this
.
_proxy
.
$provideTextSearchResults
(
this
.
_handle
,
search
.
id
,
query
.
contentPattern
,
query
);
outer
=
query
.
type
===
QueryType
.
File
?
this
.
_proxy
.
$provideFileSearchResults
(
this
.
_handle
,
search
.
id
,
query
)
:
this
.
_proxy
.
$provideTextSearchResults
(
this
.
_handle
,
search
.
id
,
query
.
contentPattern
,
query
);
if
(
token
)
{
token
.
onCancellationRequested
(()
=>
searchP
.
cancel
());
}
outer
.
then
((
result
:
ISearchCompleteStats
)
=>
{
this
.
_searches
.
delete
(
search
.
id
);
resolve
(({
results
:
values
(
search
.
matches
),
stats
:
result
.
stats
,
limitHit
:
result
.
limitHit
}));
},
err
=>
{
this
.
_searches
.
delete
(
search
.
id
);
reject
(
err
);
});
},
()
=>
{
if
(
outer
)
{
outer
.
cancel
();
}
return
searchP
.
then
((
result
:
ISearchCompleteStats
)
=>
{
this
.
_searches
.
delete
(
search
.
id
);
return
{
results
:
values
(
search
.
matches
),
stats
:
result
.
stats
,
limitHit
:
result
.
limitHit
};
},
err
=>
{
this
.
_searches
.
delete
(
search
.
id
);
return
TPromise
.
wrapError
(
err
);
});
}
...
...
src/vs/workbench/api/electron-browser/mainThreadWorkspace.ts
浏览文件 @
497ea886
...
...
@@ -24,12 +24,13 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
import
{
ITextFileService
}
from
'
vs/workbench/services/textfile/common/textfiles
'
;
import
{
IWorkspaceEditingService
}
from
'
vs/workbench/services/workspace/common/workspaceEditing
'
;
import
{
ExtHostContext
,
ExtHostWorkspaceShape
,
IExtHostContext
,
MainContext
,
MainThreadWorkspaceShape
}
from
'
../node/extHost.protocol
'
;
import
{
CancellationTokenSource
}
from
'
vs/base/common/cancellation
'
;
@
extHostNamedCustomer
(
MainContext
.
MainThreadWorkspace
)
export
class
MainThreadWorkspace
implements
MainThreadWorkspaceShape
{
private
readonly
_toDispose
:
IDisposable
[]
=
[];
private
readonly
_active
Searches
:
{
[
id
:
number
]:
TPromise
<
any
>
}
=
Object
.
create
(
null
);
private
readonly
_active
CancelTokens
:
{
[
id
:
number
]:
CancellationTokenSource
}
=
Object
.
create
(
null
);
private
readonly
_proxy
:
ExtHostWorkspaceShape
;
constructor
(
...
...
@@ -51,9 +52,9 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
dispose
():
void
{
dispose
(
this
.
_toDispose
);
for
(
let
requestId
in
this
.
_active
Searche
s
)
{
const
search
=
this
.
_activeSearche
s
[
requestId
];
search
.
cancel
();
for
(
let
requestId
in
this
.
_active
CancelToken
s
)
{
const
tokenSource
=
this
.
_activeCancelToken
s
[
requestId
];
tokenSource
.
cancel
();
}
}
...
...
@@ -157,7 +158,8 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
this
.
_searchService
.
extendQuery
(
query
);
const
search
=
this
.
_searchService
.
search
(
query
).
then
(
result
=>
{
const
tokenSource
=
new
CancellationTokenSource
();
const
search
=
this
.
_searchService
.
search
(
query
,
tokenSource
.
token
).
then
(
result
=>
{
return
result
.
results
.
map
(
m
=>
m
.
resource
);
},
err
=>
{
if
(
!
isPromiseCanceledError
(
err
))
{
...
...
@@ -166,8 +168,11 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
return
undefined
;
});
this
.
_activeSearches
[
requestId
]
=
search
;
const
onDone
=
()
=>
delete
this
.
_activeSearches
[
requestId
];
this
.
_activeCancelTokens
[
requestId
]
=
tokenSource
;
const
onDone
=
()
=>
{
tokenSource
.
dispose
();
delete
this
.
_activeCancelTokens
[
requestId
];
};
search
.
then
(
onDone
,
onDone
);
return
search
;
...
...
@@ -186,13 +191,12 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
}
};
const
search
=
this
.
_searchService
.
search
(
query
,
onProgress
).
then
(
const
tokenSource
=
new
CancellationTokenSource
();
const
search
=
this
.
_searchService
.
search
(
query
,
tokenSource
.
token
,
onProgress
).
then
(
()
=>
{
delete
this
.
_activeSearches
[
requestId
];
return
null
;
},
err
=>
{
delete
this
.
_activeSearches
[
requestId
];
if
(
!
isPromiseCanceledError
(
err
))
{
return
TPromise
.
wrapError
(
err
);
}
...
...
@@ -200,20 +204,27 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
return
undefined
;
});
this
.
_activeSearches
[
requestId
]
=
search
;
this
.
_activeCancelTokens
[
requestId
]
=
tokenSource
;
const
onDone
=
()
=>
{
tokenSource
.
dispose
();
delete
this
.
_activeCancelTokens
[
requestId
];
};
search
.
then
(
onDone
,
onDone
);
return
search
;
}
$checkExists
(
query
:
ISearchQuery
,
requestId
:
number
):
TPromise
<
boolean
>
{
query
.
exists
=
true
;
const
search
=
this
.
_searchService
.
search
(
query
).
then
(
const
tokenSource
=
new
CancellationTokenSource
();
const
search
=
this
.
_searchService
.
search
(
query
,
tokenSource
.
token
).
then
(
result
=>
{
delete
this
.
_active
Searche
s
[
requestId
];
delete
this
.
_active
CancelToken
s
[
requestId
];
return
result
.
limitHit
;
},
err
=>
{
delete
this
.
_active
Searche
s
[
requestId
];
delete
this
.
_active
CancelToken
s
[
requestId
];
if
(
!
isPromiseCanceledError
(
err
))
{
return
TPromise
.
wrapError
(
err
);
}
...
...
@@ -221,16 +232,16 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
return
undefined
;
});
this
.
_active
Searches
[
requestId
]
=
search
;
this
.
_active
CancelTokens
[
requestId
]
=
tokenSource
;
return
search
;
}
$cancelSearch
(
requestId
:
number
):
Thenable
<
boolean
>
{
const
search
=
this
.
_activeSearche
s
[
requestId
];
if
(
search
)
{
delete
this
.
_active
Searche
s
[
requestId
];
search
.
cancel
();
const
tokenSource
=
this
.
_activeCancelToken
s
[
requestId
];
if
(
tokenSource
)
{
delete
this
.
_active
CancelToken
s
[
requestId
];
tokenSource
.
cancel
();
return
TPromise
.
as
(
true
);
}
return
undefined
;
...
...
src/vs/workbench/api/node/extHostSearch.ts
浏览文件 @
497ea886
...
...
@@ -98,19 +98,15 @@ export class ExtHostSearch implements ExtHostSearchShape {
});
}
else
{
const
indexProvider
=
this
.
_fileIndexProvider
.
get
(
handle
);
if
(
indexProvider
)
{
return
this
.
_fileIndexSearchManager
.
fileSearch
(
query
,
indexProvider
,
batch
=>
{
this
.
_proxy
.
$handleFileMatch
(
handle
,
session
,
batch
.
map
(
p
=>
p
.
resource
));
}).
then
(
null
,
err
=>
{
if
(
!
isPromiseCanceledError
(
err
))
{
throw
err
;
}
return
this
.
_fileIndexSearchManager
.
fileSearch
(
query
,
indexProvider
,
batch
=>
{
this
.
_proxy
.
$handleFileMatch
(
handle
,
session
,
batch
.
map
(
p
=>
p
.
resource
));
}).
then
(
null
,
err
=>
{
if
(
!
isPromiseCanceledError
(
err
))
{
throw
err
;
}
return
null
;
});
}
else
{
throw
new
Error
(
'
something went wrong
'
);
}
return
null
;
});
}
}
...
...
@@ -300,36 +296,31 @@ class BatchedCollector<T> {
class
TextSearchEngine
{
private
activeCancellationTokens
=
new
Set
<
CancellationTokenSource
>
();
private
collector
:
TextSearchResultsCollector
;
private
isLimitHit
:
boolean
;
private
resultCount
=
0
;
private
isCanceled
:
boolean
;
constructor
(
private
pattern
:
IPatternInfo
,
private
config
:
ISearchQuery
,
private
provider
:
vscode
.
TextSearchProvider
,
private
_extfs
:
typeof
extfs
)
{
}
public
cancel
():
void
{
this
.
isCanceled
=
true
;
this
.
activeCancellationTokens
.
forEach
(
t
=>
t
.
cancel
());
this
.
activeCancellationTokens
=
new
Set
();
}
public
search
(
onProgress
:
(
matches
:
IFileMatch
[])
=>
void
):
TPromise
<
ISearchCompleteStats
>
{
const
folderQueries
=
this
.
config
.
folderQueries
;
const
tokenSource
=
new
CancellationTokenSource
();
return
new
TPromise
<
ISearchCompleteStats
>
((
resolve
,
reject
)
=>
{
this
.
collector
=
new
TextSearchResultsCollector
(
onProgress
);
let
isCanceled
=
false
;
const
onResult
=
(
match
:
vscode
.
TextSearchResult
,
folderIdx
:
number
)
=>
{
if
(
this
.
isCanceled
)
{
if
(
isCanceled
)
{
return
;
}
if
(
this
.
resultCount
>=
this
.
config
.
maxResults
)
{
this
.
isLimitHit
=
true
;
this
.
cancel
();
isCanceled
=
true
;
tokenSource
.
cancel
();
}
if
(
!
this
.
isLimitHit
)
{
...
...
@@ -340,8 +331,9 @@ class TextSearchEngine {
// For each root folder
TPromise
.
join
(
folderQueries
.
map
((
fq
,
i
)
=>
{
return
this
.
searchInFolder
(
fq
,
r
=>
onResult
(
r
,
i
));
return
this
.
searchInFolder
(
fq
,
r
=>
onResult
(
r
,
i
)
,
tokenSource
.
token
);
})).
then
(()
=>
{
tokenSource
.
dispose
();
this
.
collector
.
flush
();
resolve
({
limitHit
:
this
.
isLimitHit
,
...
...
@@ -350,17 +342,20 @@ class TextSearchEngine {
}
});
},
(
errs
:
Error
[])
=>
{
tokenSource
.
dispose
();
const
errMsg
=
errs
.
map
(
err
=>
toErrorMessage
(
err
))
.
filter
(
msg
=>
!!
msg
)[
0
];
reject
(
new
Error
(
errMsg
));
});
},
()
=>
{
// From IPC
tokenSource
.
cancel
();
});
}
private
searchInFolder
(
folderQuery
:
IFolderQuery
<
URI
>
,
onResult
:
(
result
:
vscode
.
TextSearchResult
)
=>
void
):
TPromise
<
void
>
{
let
cancellation
=
new
CancellationTokenSource
();
private
searchInFolder
(
folderQuery
:
IFolderQuery
<
URI
>
,
onResult
:
(
result
:
vscode
.
TextSearchResult
)
=>
void
,
token
:
CancellationToken
):
TPromise
<
void
>
{
return
new
TPromise
((
resolve
,
reject
)
=>
{
const
queryTester
=
new
QueryGlobTester
(
this
.
config
,
folderQuery
);
...
...
@@ -385,22 +380,14 @@ class TextSearchEngine {
const
searchOptions
=
this
.
getSearchOptionsForFolder
(
folderQuery
);
new
TPromise
(
resolve
=>
process
.
nextTick
(
resolve
))
.
then
(()
=>
{
this
.
activeCancellationTokens
.
add
(
cancellation
);
return
this
.
provider
.
provideTextSearchResults
(
patternInfoToQuery
(
this
.
pattern
),
searchOptions
,
progress
,
cancellation
.
token
);
return
this
.
provider
.
provideTextSearchResults
(
patternInfoToQuery
(
this
.
pattern
),
searchOptions
,
progress
,
token
);
})
.
then
(()
=>
{
this
.
activeCancellationTokens
.
delete
(
cancellation
);
return
TPromise
.
join
(
testingPs
);
})
.
then
(
()
=>
{
cancellation
.
dispose
();
resolve
(
null
);
},
err
=>
{
cancellation
.
dispose
();
reject
(
err
);
});
()
=>
resolve
(
null
),
reject
);
});
}
...
...
src/vs/workbench/parts/search/browser/openFileHandler.ts
浏览文件 @
497ea886
...
...
@@ -172,8 +172,7 @@ export class OpenFileHandler extends QuickOpenHandler {
return
TPromise
.
wrap
(
<
ISearchComplete
>
{
results
:
[{
resource
:
result
}]
});
}
// TODO@Rob support cancellation
return
this
.
searchService
.
search
(
this
.
queryBuilder
.
file
(
this
.
contextService
.
getWorkspace
().
folders
.
map
(
folder
=>
folder
.
uri
),
queryOptions
));
return
this
.
searchService
.
search
(
this
.
queryBuilder
.
file
(
this
.
contextService
.
getWorkspace
().
folders
.
map
(
folder
=>
folder
.
uri
),
queryOptions
),
token
);
}).
then
(
complete
=>
{
const
results
:
QuickOpenEntry
[]
=
[];
for
(
let
i
=
0
;
i
<
complete
.
results
.
length
;
i
++
)
{
...
...
src/vs/workbench/parts/search/common/searchModel.ts
浏览文件 @
497ea886
...
...
@@ -24,6 +24,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import
{
overviewRulerFindMatchForeground
}
from
'
vs/platform/theme/common/colorRegistry
'
;
import
{
themeColorFromId
}
from
'
vs/platform/theme/common/themeService
'
;
import
{
IReplaceService
}
from
'
vs/workbench/parts/search/common/replace
'
;
import
{
CancellationTokenSource
}
from
'
vs/base/common/cancellation
'
;
export
class
Match
{
...
...
@@ -733,7 +734,7 @@ export class SearchModel extends Disposable {
private
readonly
_onReplaceTermChanged
:
Emitter
<
void
>
=
this
.
_register
(
new
Emitter
<
void
>
());
public
readonly
onReplaceTermChanged
:
Event
<
void
>
=
this
.
_onReplaceTermChanged
.
event
;
private
current
Request
:
TPromise
<
ISearchComplete
>
;
private
current
CancelTokenSource
:
CancellationTokenSource
;
constructor
(@
ISearchService
private
searchService
:
ISearchService
,
@
ITelemetryService
private
telemetryService
:
ITelemetryService
,
@
IInstantiationService
private
instantiationService
:
IInstantiationService
)
{
super
();
...
...
@@ -778,7 +779,8 @@ export class SearchModel extends Disposable {
const
progressEmitter
=
new
Emitter
<
void
>
();
this
.
_replacePattern
=
new
ReplacePattern
(
this
.
_replaceString
,
this
.
_searchQuery
.
contentPattern
);
this
.
currentRequest
=
this
.
searchService
.
search
(
this
.
_searchQuery
,
p
=>
{
const
tokenSource
=
this
.
currentCancelTokenSource
=
new
CancellationTokenSource
();
const
currentRequest
=
this
.
searchService
.
search
(
this
.
_searchQuery
,
this
.
currentCancelTokenSource
.
token
,
p
=>
{
progressEmitter
.
fire
();
this
.
onSearchProgress
(
p
);
...
...
@@ -787,7 +789,10 @@ export class SearchModel extends Disposable {
}
});
const
onDone
=
fromPromise
(
this
.
currentRequest
);
const
dispose
=
()
=>
tokenSource
.
dispose
();
currentRequest
.
then
(
dispose
,
dispose
);
const
onDone
=
fromPromise
(
currentRequest
);
const
onFirstRender
=
anyEvent
<
any
>
(
onDone
,
progressEmitter
.
event
);
const
onFirstRenderStopwatch
=
stopwatch
(
onFirstRender
);
/* __GDPR__
...
...
@@ -807,18 +812,14 @@ export class SearchModel extends Disposable {
*/
onDoneStopwatch
(
duration
=>
this
.
telemetryService
.
publicLog
(
'
searchResultsFinished
'
,
{
duration
}));
const
currentRequest
=
this
.
currentRequest
;
this
.
currentRequest
.
then
(
currentRequest
.
then
(
value
=>
this
.
onSearchCompleted
(
value
,
Date
.
now
()
-
start
),
e
=>
this
.
onSearchError
(
e
,
Date
.
now
()
-
start
));
// this.currentRequest may be completed (and nulled) immediately
return
currentRequest
;
}
private
onSearchCompleted
(
completed
:
ISearchComplete
,
duration
:
number
):
ISearchComplete
{
this
.
currentRequest
=
null
;
const
options
:
IPatternInfo
=
objects
.
assign
({},
this
.
_searchQuery
.
contentPattern
);
delete
options
.
pattern
;
...
...
@@ -866,9 +867,8 @@ export class SearchModel extends Disposable {
}
public
cancelSearch
():
boolean
{
if
(
this
.
currentRequest
)
{
this
.
currentRequest
.
cancel
();
this
.
currentRequest
=
null
;
if
(
this
.
currentCancelTokenSource
)
{
this
.
currentCancelTokenSource
.
cancel
();
return
true
;
}
return
false
;
...
...
src/vs/workbench/parts/search/test/common/searchModel.test.ts
浏览文件 @
497ea886
...
...
@@ -20,6 +20,7 @@ import { IFileMatch, IFileSearchStats, IFolderQuery, ISearchComplete, ISearchPro
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
NullTelemetryService
}
from
'
vs/platform/telemetry/common/telemetryUtils
'
;
import
{
SearchModel
}
from
'
vs/workbench/parts/search/common/searchModel
'
;
import
{
CancellationToken
,
CancellationTokenSource
}
from
'
vs/base/common/cancellation
'
;
const
nullEvent
=
new
class
{
...
...
@@ -83,7 +84,7 @@ suite('SearchModel', () => {
function
searchServiceWithResults
(
results
:
IFileMatch
[],
complete
:
ISearchComplete
=
null
):
ISearchService
{
return
<
ISearchService
>
{
search
(
query
:
ISearchQuery
,
onProgress
:
(
result
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
{
search
(
query
:
ISearchQuery
,
token
?:
CancellationToken
,
onProgress
?
:
(
result
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
{
return
new
TPromise
(
resolve
=>
{
process
.
nextTick
(()
=>
{
results
.
forEach
(
onProgress
);
...
...
@@ -96,7 +97,7 @@ suite('SearchModel', () => {
function
searchServiceWithError
(
error
:
Error
):
ISearchService
{
return
<
ISearchService
>
{
search
(
query
:
ISearchQuery
,
onProgress
:
(
result
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
{
search
(
query
:
ISearchQuery
,
token
?:
CancellationToken
,
onProgress
?
:
(
result
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
{
return
new
TPromise
((
resolve
,
reject
)
=>
{
reject
(
error
);
});
...
...
@@ -104,6 +105,22 @@ suite('SearchModel', () => {
};
}
function
canceleableSearchService
(
tokenSource
:
CancellationTokenSource
):
ISearchService
{
return
<
ISearchService
>
{
search
(
query
:
ISearchQuery
,
token
?:
CancellationToken
,
onProgress
?:
(
result
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
{
if
(
token
)
{
token
.
onCancellationRequested
(()
=>
tokenSource
.
cancel
());
}
return
new
TPromise
(
resolve
=>
{
process
.
nextTick
(()
=>
{
resolve
(
<
any
>
{});
});
});
}
};
}
test
(
'
Search Model: Search adds to results
'
,
async
()
=>
{
let
results
=
[
aRawMatch
(
'
file://c:/1
'
,
...
...
@@ -257,15 +274,15 @@ suite('SearchModel', () => {
});
test
(
'
Search Model: Previous search is cancelled when new search is called
'
,
async
()
=>
{
let
target
=
sinon
.
spy
();
instantiationService
.
stub
(
ISearchService
,
'
search
'
,
new
DeferredTPromise
(
target
));
le
t
testObject
:
SearchModel
=
instantiationService
.
createInstance
(
SearchModel
);
const
tokenSource
=
new
CancellationTokenSource
();
instantiationService
.
stub
(
ISearchService
,
canceleableSearchService
(
tokenSource
));
cons
t
testObject
:
SearchModel
=
instantiationService
.
createInstance
(
SearchModel
);
testObject
.
search
({
contentPattern
:
{
pattern
:
'
somestring
'
},
type
:
1
,
folderQueries
});
instantiationService
.
stub
(
ISearchService
,
searchServiceWithResults
([]));
testObject
.
search
({
contentPattern
:
{
pattern
:
'
somestring
'
},
type
:
1
,
folderQueries
});
assert
.
ok
(
t
arget
.
calledOnce
);
assert
.
ok
(
t
okenSource
.
token
.
isCancellationRequested
);
});
test
(
'
getReplaceString returns proper replace string for regExpressions
'
,
async
()
=>
{
...
...
src/vs/workbench/services/search/node/searchService.ts
浏览文件 @
497ea886
...
...
@@ -30,6 +30,8 @@ import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/un
import
{
IRawSearch
,
IRawSearchService
,
ISerializedFileMatch
,
ISerializedSearchComplete
,
ISerializedSearchProgressItem
,
isSerializedSearchComplete
,
isSerializedSearchSuccess
}
from
'
./search
'
;
import
{
ISearchChannel
,
SearchChannelClient
}
from
'
./searchIpc
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
canceled
}
from
'
vs/base/common/errors
'
;
export
class
SearchService
extends
Disposable
implements
ISearchService
{
public
_serviceBrand
:
any
;
...
...
@@ -92,65 +94,62 @@ export class SearchService extends Disposable implements ISearchService {
}
}
public
search
(
query
:
ISearchQuery
,
onProgress
?:
(
item
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
{
let
combinedPromise
:
TPromise
<
void
>
;
public
search
(
query
:
ISearchQuery
,
token
?:
CancellationToken
,
onProgress
?:
(
item
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
{
// Get local results from dirty/untitled
const
localResults
=
this
.
getLocalResults
(
query
);
return
new
TPromise
<
ISearchComplete
>
((
onComplete
,
onError
)
=>
{
// Get local results from dirty/untitled
const
localResults
=
this
.
getLocalResults
(
query
);
if
(
onProgress
)
{
localResults
.
values
().
filter
((
res
)
=>
!!
res
).
forEach
(
onProgress
);
}
if
(
onProgress
)
{
localResults
.
values
().
filter
((
res
)
=>
!!
res
).
forEach
(
onProgress
);
}
this
.
logService
.
trace
(
'
SearchService#search
'
,
JSON
.
stringify
(
query
));
this
.
logService
.
trace
(
'
SearchService#search
'
,
JSON
.
stringify
(
query
));
const
onProviderProgress
=
progress
=>
{
if
(
progress
.
resource
)
{
// Match
if
(
!
localResults
.
has
(
progress
.
resource
)
&&
onProgress
)
{
// don't override local results
onProgress
(
progress
);
}
}
else
if
(
onProgress
)
{
// Progress
onProgress
(
<
IProgress
>
progress
);
const
onProviderProgress
=
progress
=>
{
if
(
progress
.
resource
)
{
// Match
if
(
!
localResults
.
has
(
progress
.
resource
)
&&
onProgress
)
{
// don't override local results
onProgress
(
progress
);
}
}
else
if
(
onProgress
)
{
// Progress
onProgress
(
<
IProgress
>
progress
);
}
if
(
progress
.
message
)
{
this
.
logService
.
debug
(
'
SearchService#search
'
,
progress
.
message
);
}
};
if
(
progress
.
message
)
{
this
.
logService
.
debug
(
'
SearchService#search
'
,
progress
.
message
);
}
};
const
schemesInQuery
=
this
.
getSchemesInQuery
(
query
);
const
schemesInQuery
=
this
.
getSchemesInQuery
(
query
);
const
providerActivations
:
TPromise
<
any
>
[]
=
[
TPromise
.
wrap
(
null
)];
schemesInQuery
.
forEach
(
scheme
=>
providerActivations
.
push
(
this
.
extensionService
.
activateByEvent
(
`onSearch:
${
scheme
}
`
)));
const
providerActivations
:
TPromise
<
any
>
[]
=
[
TPromise
.
wrap
(
null
)];
schemesInQuery
.
forEach
(
scheme
=>
providerActivations
.
push
(
this
.
extensionService
.
activateByEvent
(
`onSearch:
${
scheme
}
`
)));
const
providerPromise
=
TPromise
.
join
(
providerActivations
)
.
then
(()
=>
this
.
extensionService
.
whenInstalledExtensionsRegistered
())
.
then
(()
=>
this
.
searchWithProviders
(
query
,
onProviderProgress
))
.
then
(
completes
=>
{
completes
=
completes
.
filter
(
c
=>
!!
c
);
if
(
!
completes
.
length
)
{
return
null
;
}
const
providerPromise
=
TPromise
.
join
(
providerActivations
)
.
then
(()
=>
this
.
extensionService
.
whenInstalledExtensionsRegistered
())
.
then
(()
=>
this
.
searchWithProviders
(
query
,
onProviderProgress
,
token
))
.
then
(
completes
=>
{
completes
=
completes
.
filter
(
c
=>
!!
c
);
if
(
!
completes
.
length
)
{
return
null
;
}
return
<
ISearchComplete
>
{
limitHit
:
completes
[
0
]
&&
completes
[
0
].
limitHit
,
stats
:
completes
[
0
].
stats
,
results
:
arrays
.
flatten
(
completes
.
map
(
c
=>
c
.
results
))
};
},
errs
=>
{
if
(
!
Array
.
isArray
(
errs
))
{
errs
=
[
errs
];
}
return
<
ISearchComplete
>
{
limitHit
:
completes
[
0
]
&&
completes
[
0
].
limitHit
,
stats
:
completes
[
0
].
stats
,
results
:
arrays
.
flatten
(
completes
.
map
(
c
=>
c
.
results
))
};
},
errs
=>
{
if
(
!
Array
.
isArray
(
errs
))
{
errs
=
[
errs
];
}
errs
=
errs
.
filter
(
e
=>
!!
e
);
return
TPromise
.
wrapError
(
errs
[
0
]);
});
errs
=
errs
.
filter
(
e
=>
!!
e
);
return
TPromise
.
wrapError
(
errs
[
0
]);
});
combinedPromise
=
providerPromise
.
then
(
value
=>
{
return
new
TPromise
((
c
,
e
)
=>
{
providerPromise
.
then
(
value
=>
{
const
values
=
[
value
];
const
result
:
ISearchComplete
=
{
...
...
@@ -177,10 +176,11 @@ export class SearchService extends Disposable implements ISearchService {
}
return
result
;
}).
then
(
c
,
e
);
},
()
=>
{
// Need the OpenAnythingHandler to stop trying to cancel this promise, https://github.com/Microsoft/vscode/issues/56137
});
}).
then
(
onComplete
,
onError
);
},
()
=>
combinedPromise
&&
combinedPromise
.
cancel
());
}
private
getSchemesInQuery
(
query
:
ISearchQuery
):
Set
<
string
>
{
...
...
@@ -196,7 +196,7 @@ export class SearchService extends Disposable implements ISearchService {
return
schemes
;
}
private
searchWithProviders
(
query
:
ISearchQuery
,
onProviderProgress
:
(
progress
:
ISearchProgressItem
)
=>
void
)
{
private
searchWithProviders
(
query
:
ISearchQuery
,
onProviderProgress
:
(
progress
:
ISearchProgressItem
)
=>
void
,
token
?:
CancellationToken
)
{
const
e2eSW
=
StopWatch
.
create
(
false
);
const
diskSearchQueries
:
IFolderQuery
[]
=
[];
...
...
@@ -219,7 +219,7 @@ export class SearchService extends Disposable implements ISearchService {
}
};
searchPs
.
push
(
provider
.
search
(
oneFolderQuery
,
onProviderProgress
));
searchPs
.
push
(
provider
.
search
(
oneFolderQuery
,
onProviderProgress
,
token
));
}
});
...
...
@@ -234,7 +234,7 @@ export class SearchService extends Disposable implements ISearchService {
extraFileResources
:
diskSearchExtraFileResources
};
searchPs
.
push
(
this
.
diskSearch
.
search
(
diskSearchQuery
,
onProviderProgress
));
searchPs
.
push
(
this
.
diskSearch
.
search
(
diskSearchQuery
,
onProviderProgress
,
token
));
}
return
TPromise
.
join
(
searchPs
).
then
(
completes
=>
{
...
...
@@ -447,7 +447,7 @@ export class DiskSearch implements ISearchResultProvider {
this
.
raw
=
new
SearchChannelClient
(
channel
);
}
public
search
(
query
:
ISearchQuery
,
onProgress
?:
(
p
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
{
public
search
(
query
:
ISearchQuery
,
onProgress
?:
(
p
:
ISearchProgressItem
)
=>
void
,
token
?:
CancellationToken
):
TPromise
<
ISearchComplete
>
{
const
folderQueries
=
query
.
folderQueries
||
[];
return
TPromise
.
join
(
folderQueries
.
map
(
q
=>
q
.
folder
.
scheme
===
Schemas
.
file
&&
pfs
.
exists
(
q
.
folder
.
fsPath
)))
.
then
(
exists
=>
{
...
...
@@ -461,7 +461,7 @@ export class DiskSearch implements ISearchResultProvider {
event
=
this
.
raw
.
textSearch
(
rawSearch
);
}
return
DiskSearch
.
collectResultsFromEvent
(
event
,
onProgress
);
return
DiskSearch
.
collectResultsFromEvent
(
event
,
onProgress
,
token
);
});
}
...
...
@@ -507,11 +507,21 @@ export class DiskSearch implements ISearchResultProvider {
return
rawSearch
;
}
public
static
collectResultsFromEvent
(
event
:
Event
<
ISerializedSearchProgressItem
|
ISerializedSearchComplete
>
,
onProgress
?:
(
p
:
ISearchProgressItem
)
=>
void
):
TPromise
<
ISearchComplete
>
{
public
static
collectResultsFromEvent
(
event
:
Event
<
ISerializedSearchProgressItem
|
ISerializedSearchComplete
>
,
onProgress
?:
(
p
:
ISearchProgressItem
)
=>
void
,
token
?:
CancellationToken
):
TPromise
<
ISearchComplete
>
{
let
result
:
IFileMatch
[]
=
[];
let
listener
:
IDisposable
;
return
new
TPromise
<
ISearchComplete
>
((
c
,
e
)
=>
{
if
(
token
)
{
token
.
onCancellationRequested
(()
=>
{
if
(
listener
)
{
listener
.
dispose
();
}
e
(
canceled
());
});
}
listener
=
event
(
ev
=>
{
if
(
isSerializedSearchComplete
(
ev
))
{
if
(
isSerializedSearchSuccess
(
ev
))
{
...
...
@@ -551,8 +561,7 @@ export class DiskSearch implements ISearchResultProvider {
}
}
});
},
()
=>
listener
&&
listener
.
dispose
());
});
}
private
static
createFileMatch
(
data
:
ISerializedFileMatch
):
FileMatch
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录