Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
b7e684c5
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b7e684c5
编写于
9月 10, 2018
作者:
R
Rob Lourens
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix TPromise#cancel in FileIndexProvider #56137
上级
b9dbeb90
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
83 addition
and
101 deletion
+83
-101
src/vs/base/test/common/utils.ts
src/vs/base/test/common/utils.ts
+5
-0
src/vs/workbench/api/node/extHostSearch.fileIndex.ts
src/vs/workbench/api/node/extHostSearch.fileIndex.ts
+73
-79
src/vs/workbench/api/node/extHostSearch.ts
src/vs/workbench/api/node/extHostSearch.ts
+5
-22
未找到文件。
src/vs/base/test/common/utils.ts
浏览文件 @
b7e684c5
...
...
@@ -8,6 +8,7 @@
import
*
as
paths
from
'
vs/base/common/paths
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
TPromise
,
TValueCallback
}
from
'
vs/base/common/winjs.base
'
;
import
{
canceled
}
from
'
vs/base/common/errors
'
;
export
class
DeferredTPromise
<
T
>
extends
TPromise
<
T
>
{
...
...
@@ -30,6 +31,10 @@ export class DeferredTPromise<T> extends TPromise<T> {
public
error
(
err
:
any
)
{
this
.
errorCallback
(
err
);
}
public
cancel
()
{
this
.
errorCallback
(
canceled
());
}
}
export
function
toResource
(
this
:
any
,
path
:
string
)
{
...
...
src/vs/workbench/api/node/extHostSearch.fileIndex.ts
浏览文件 @
b7e684c5
...
...
@@ -6,8 +6,10 @@
import
*
as
path
from
'
path
'
;
import
*
as
arrays
from
'
vs/base/common/arrays
'
;
import
{
CancellationTokenSource
}
from
'
vs/base/common/cancellation
'
;
import
{
CancelablePromise
,
createCancelablePromise
}
from
'
vs/base/common/async
'
;
import
{
CancellationToken
,
CancellationTokenSource
}
from
'
vs/base/common/cancellation
'
;
import
{
toErrorMessage
}
from
'
vs/base/common/errorMessage
'
;
import
{
canceled
}
from
'
vs/base/common/errors
'
;
import
*
as
glob
from
'
vs/base/common/glob
'
;
import
*
as
resources
from
'
vs/base/common/resources
'
;
import
{
StopWatch
}
from
'
vs/base/common/stopwatch
'
;
...
...
@@ -15,9 +17,8 @@ import * as strings from 'vs/base/common/strings';
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
compareItemsByScore
,
IItemAccessor
,
prepareQuery
,
ScorerCache
}
from
'
vs/base/parts/quickopen/common/quickOpenScorer
'
;
import
{
ICachedSearchStats
,
IFile
Match
,
IFolderQuery
,
IRawSearchQuery
,
ISearchCompleteStats
,
ISearchQuery
,
IFileSearchStats
,
IFileIndexProviderStats
}
from
'
vs/platform/search/common/search
'
;
import
{
ICachedSearchStats
,
IFile
IndexProviderStats
,
IFileMatch
,
IFileSearchStats
,
IFolderQuery
,
IRawSearchQuery
,
ISearchCompleteStats
,
ISearchQuery
}
from
'
vs/platform/search/common/search
'
;
import
*
as
vscode
from
'
vscode
'
;
import
{
canceled
}
from
'
vs/base/common/errors
'
;
export
interface
IInternalFileMatch
{
base
:
URI
;
...
...
@@ -418,9 +419,9 @@ export class FileIndexSearchManager {
private
readonly
folderCacheKeys
=
new
Map
<
string
,
Set
<
string
>>
();
public
fileSearch
(
config
:
ISearchQuery
,
provider
:
vscode
.
FileIndexProvider
,
onBatch
:
(
matches
:
IFileMatch
[])
=>
void
):
TPromise
<
ISearchCompleteStats
>
{
public
fileSearch
(
config
:
ISearchQuery
,
provider
:
vscode
.
FileIndexProvider
,
onBatch
:
(
matches
:
IFileMatch
[])
=>
void
,
token
:
CancellationToken
):
TPromise
<
ISearchCompleteStats
>
{
if
(
config
.
sortByScore
)
{
let
sortedSearch
=
this
.
trySortedSearchFromCache
(
config
);
let
sortedSearch
=
this
.
trySortedSearchFromCache
(
config
,
token
);
if
(
!
sortedSearch
)
{
const
engineConfig
=
config
.
maxResults
?
{
...
...
@@ -430,21 +431,17 @@ export class FileIndexSearchManager {
config
;
const
engine
=
new
FileIndexSearchEngine
(
engineConfig
,
provider
);
sortedSearch
=
this
.
doSortedSearch
(
engine
,
config
);
sortedSearch
=
this
.
doSortedSearch
(
engine
,
config
,
token
);
}
return
new
TPromise
<
ISearchCompleteStats
>
((
c
,
e
)
=>
{
sortedSearch
.
then
(
complete
=>
{
this
.
sendAsBatches
(
complete
.
results
,
onBatch
,
FileIndexSearchManager
.
BATCH_SIZE
);
c
(
complete
);
},
e
);
},
()
=>
{
sortedSearch
.
cancel
();
return
sortedSearch
.
then
(
complete
=>
{
this
.
sendAsBatches
(
complete
.
results
,
onBatch
,
FileIndexSearchManager
.
BATCH_SIZE
);
return
complete
;
});
}
const
engine
=
new
FileIndexSearchEngine
(
config
,
provider
);
return
this
.
doSearch
(
engine
)
return
this
.
doSearch
(
engine
,
token
)
.
then
(
complete
=>
{
this
.
sendAsBatches
(
complete
.
results
,
onBatch
,
FileIndexSearchManager
.
BATCH_SIZE
);
return
<
ISearchCompleteStats
>
{
...
...
@@ -477,12 +474,9 @@ export class FileIndexSearchManager {
};
}
private
doSortedSearch
(
engine
:
FileIndexSearchEngine
,
config
:
ISearchQuery
):
TPromise
<
IInternalSearchComplete
>
{
let
searchPromise
:
TPromise
<
void
>
;
let
allResultsPromise
=
new
TPromise
<
IInternalSearchComplete
<
IFileIndexProviderStats
>>
((
c
,
e
)
=>
{
searchPromise
=
this
.
doSearch
(
engine
).
then
(
c
,
e
);
},
()
=>
{
searchPromise
.
cancel
();
private
doSortedSearch
(
engine
:
FileIndexSearchEngine
,
config
:
ISearchQuery
,
token
:
CancellationToken
):
TPromise
<
IInternalSearchComplete
>
{
let
allResultsPromise
=
createCancelablePromise
<
IInternalSearchComplete
<
IFileIndexProviderStats
>>
(
token
=>
{
return
this
.
doSearch
(
engine
,
token
);
});
const
folderCacheKey
=
this
.
getFolderCacheKey
(
config
);
...
...
@@ -502,17 +496,16 @@ export class FileIndexSearchManager {
allResultsPromise
=
this
.
preventCancellation
(
allResultsPromise
);
}
let
chained
:
TPromise
<
void
>
;
return
new
TPromise
<
IInternalSearchComplete
>
((
c
,
e
)
=>
{
chained
=
allResultsPromise
.
then
(
complete
=>
{
return
TPromise
.
wrap
<
IInternalSearchComplete
>
(
allResultsPromise
.
then
(
complete
=>
{
const
scorerCache
:
ScorerCache
=
cache
?
cache
.
scorerCache
:
Object
.
create
(
null
);
const
sortSW
=
(
typeof
config
.
maxResults
!==
'
number
'
||
config
.
maxResults
>
0
)
&&
StopWatch
.
create
();
return
this
.
sortResults
(
config
,
complete
.
results
,
scorerCache
)
return
this
.
sortResults
(
config
,
complete
.
results
,
scorerCache
,
token
)
.
then
(
sortedResults
=>
{
// sortingTime: -1 indicates a "sorted" search that was not sorted, i.e. populating the cache when quickopen is opened.
// Contrasting with findFiles which is not sorted and will have sortingTime: undefined
const
sortingTime
=
sortSW
?
sortSW
.
elapsed
()
:
-
1
;
c
(
<
IInternalSearchComplete
>
{
return
<
IInternalSearchComplete
>
{
limitHit
:
complete
.
limitHit
||
typeof
config
.
maxResults
===
'
number
'
&&
complete
.
results
.
length
>
config
.
maxResults
,
// ??
results
:
sortedResults
,
stats
:
{
...
...
@@ -522,12 +515,9 @@ export class FileIndexSearchManager {
sortingTime
,
type
:
'
fileIndexProvider
'
}
}
)
;
};
});
},
e
);
},
()
=>
{
chained
.
cancel
();
});
}));
}
private
getOrCreateCache
(
cacheKey
:
string
):
Cache
{
...
...
@@ -538,42 +528,41 @@ export class FileIndexSearchManager {
return
this
.
caches
[
cacheKey
]
=
new
Cache
();
}
private
trySortedSearchFromCache
(
config
:
ISearchQuery
):
TPromise
<
IInternalSearchComplete
>
{
private
trySortedSearchFromCache
(
config
:
ISearchQuery
,
token
:
CancellationToken
):
TPromise
<
IInternalSearchComplete
>
{
const
folderCacheKey
=
this
.
getFolderCacheKey
(
config
);
const
cache
=
folderCacheKey
&&
this
.
caches
[
folderCacheKey
];
if
(
!
cache
)
{
return
undefined
;
}
const
cached
=
this
.
getResultsFromCache
(
cache
,
config
.
filePattern
);
const
cached
=
this
.
getResultsFromCache
(
cache
,
config
.
filePattern
,
token
);
if
(
cached
)
{
let
chained
:
TPromise
<
void
>
;
return
new
TPromise
<
IInternalSearchComplete
>
((
c
,
e
)
=>
{
chained
=
cached
.
then
(
complete
=>
{
const
sortSW
=
StopWatch
.
create
();
return
this
.
sortResults
(
config
,
complete
.
results
,
cache
.
scorerCache
)
.
then
(
sortedResults
=>
{
c
(
<
IInternalSearchComplete
<
IFileSearchStats
>>
{
limitHit
:
complete
.
limitHit
||
typeof
config
.
maxResults
===
'
number
'
&&
complete
.
results
.
length
>
config
.
maxResults
,
results
:
sortedResults
,
stats
:
{
fromCache
:
true
,
detailStats
:
complete
.
stats
,
type
:
'
fileIndexProvider
'
,
resultCount
:
sortedResults
.
length
,
sortingTime
:
sortSW
.
elapsed
()
}
});
});
},
e
);
},
()
=>
{
chained
.
cancel
();
return
cached
.
then
(
complete
=>
{
const
sortSW
=
StopWatch
.
create
();
return
this
.
sortResults
(
config
,
complete
.
results
,
cache
.
scorerCache
,
token
)
.
then
(
sortedResults
=>
{
if
(
token
&&
token
.
isCancellationRequested
)
{
throw
canceled
();
}
return
<
IInternalSearchComplete
<
IFileSearchStats
>>
{
limitHit
:
complete
.
limitHit
||
typeof
config
.
maxResults
===
'
number
'
&&
complete
.
results
.
length
>
config
.
maxResults
,
results
:
sortedResults
,
stats
:
{
fromCache
:
true
,
detailStats
:
complete
.
stats
,
type
:
'
fileIndexProvider
'
,
resultCount
:
sortedResults
.
length
,
sortingTime
:
sortSW
.
elapsed
()
}
};
});
});
}
return
undefined
;
}
private
sortResults
(
config
:
IRawSearchQuery
,
results
:
IInternalFileMatch
[],
scorerCache
:
ScorerCache
):
TPromise
<
IInternalFileMatch
[]
>
{
private
sortResults
(
config
:
IRawSearchQuery
,
results
:
IInternalFileMatch
[],
scorerCache
:
ScorerCache
,
token
:
CancellationToken
):
TPromise
<
IInternalFileMatch
[]
>
{
// we use the same compare function that is used later when showing the results using fuzzy scoring
// this is very important because we are also limiting the number of results by config.maxResults
// and as such we want the top items to be included in this result set if the number of items
...
...
@@ -581,7 +570,7 @@ export class FileIndexSearchManager {
const
query
=
prepareQuery
(
config
.
filePattern
);
const
compare
=
(
matchA
:
IInternalFileMatch
,
matchB
:
IInternalFileMatch
)
=>
compareItemsByScore
(
matchA
,
matchB
,
query
,
true
,
FileMatchItemAccessor
,
scorerCache
);
return
arrays
.
topAsync
(
results
,
compare
,
config
.
maxResults
,
10000
);
return
arrays
.
topAsync
(
results
,
compare
,
config
.
maxResults
,
10000
,
token
);
}
private
sendAsBatches
(
rawMatches
:
IInternalFileMatch
[],
onBatch
:
(
batch
:
IFileMatch
[])
=>
void
,
batchSize
:
number
)
{
...
...
@@ -595,7 +584,7 @@ export class FileIndexSearchManager {
}
}
private
getResultsFromCache
(
cache
:
Cache
,
searchValue
:
string
):
TPromise
<
IInternalSearchComplete
<
ICachedSearchStats
>>
{
private
getResultsFromCache
(
cache
:
Cache
,
searchValue
:
string
,
token
:
CancellationToken
):
TPromise
<
IInternalSearchComplete
<
ICachedSearchStats
>>
{
const
cacheLookupSW
=
StopWatch
.
create
();
if
(
path
.
isAbsolute
(
searchValue
))
{
...
...
@@ -630,7 +619,13 @@ export class FileIndexSearchManager {
const
cacheFilterSW
=
StopWatch
.
create
();
return
new
TPromise
<
IInternalSearchComplete
<
ICachedSearchStats
>>
((
c
,
e
)
=>
{
token
.
onCancellationRequested
(()
=>
e
(
canceled
()));
cacheRow
.
promise
.
then
(
complete
=>
{
if
(
token
&&
token
.
isCancellationRequested
)
{
e
(
canceled
());
}
// Pattern match on results
let
results
:
IInternalFileMatch
[]
=
[];
const
normalizedSearchValueLowercase
=
strings
.
stripWildcards
(
searchValue
).
toLowerCase
();
...
...
@@ -656,24 +651,20 @@ export class FileIndexSearchManager {
}
});
},
e
);
},
()
=>
{
cacheRow
.
promise
.
cancel
();
});
}
private
doSearch
(
engine
:
FileIndexSearchEngine
):
TPromise
<
IInternalSearchComplete
<
IFileIndexProviderStats
>>
{
private
doSearch
(
engine
:
FileIndexSearchEngine
,
token
:
CancellationToken
):
TPromise
<
IInternalSearchComplete
<
IFileIndexProviderStats
>>
{
token
.
onCancellationRequested
(()
=>
engine
.
cancel
());
const
results
:
IInternalFileMatch
[]
=
[];
const
onResult
=
match
=>
results
.
push
(
match
);
return
new
TPromise
<
IInternalSearchComplete
<
IFileIndexProviderStats
>>
((
c
,
e
)
=>
{
engine
.
search
(
onResult
).
then
(
result
=>
{
c
(
<
IInternalSearchComplete
<
IFileIndexProviderStats
>>
{
limitHit
:
result
.
isLimitHit
,
results
,
stats
:
result
.
stats
});
},
e
);
},
()
=>
{
engine
.
cancel
();
return
engine
.
search
(
onResult
).
then
(
result
=>
{
return
<
IInternalSearchComplete
<
IFileIndexProviderStats
>>
{
limitHit
:
result
.
isLimitHit
,
results
,
stats
:
result
.
stats
};
});
}
...
...
@@ -690,20 +681,23 @@ export class FileIndexSearchManager {
return
TPromise
.
as
(
undefined
);
}
private
preventCancellation
<
C
>
(
promise
:
TPromise
<
C
>
):
TPromise
<
C
>
{
return
new
TPromise
<
C
>
((
c
,
e
)
=>
{
// Allow for piled up cancellations to come through first.
process
.
nextTick
(()
=>
{
promise
.
then
(
c
,
e
);
});
},
()
=>
{
// Do not propagate.
});
private
preventCancellation
<
C
>
(
promise
:
CancelablePromise
<
C
>
):
CancelablePromise
<
C
>
{
return
new
class
implements
CancelablePromise
<
C
>
{
cancel
()
{
// Do nothing
}
then
(
resolve
,
reject
)
{
return
promise
.
then
(
resolve
,
reject
);
}
catch
(
reject
?)
{
return
this
.
then
(
undefined
,
reject
);
}
};
}
}
interface
ICacheRow
{
promise
:
T
Promise
<
IInternalSearchComplete
<
IFileIndexProviderStats
>>
;
promise
:
Cancelable
Promise
<
IInternalSearchComplete
<
IFileIndexProviderStats
>>
;
resolved
:
boolean
;
}
...
...
src/vs/workbench/api/node/extHostSearch.ts
浏览文件 @
b7e684c5
...
...
@@ -7,7 +7,6 @@
import
*
as
path
from
'
path
'
;
import
{
CancellationToken
,
CancellationTokenSource
}
from
'
vs/base/common/cancellation
'
;
import
{
toErrorMessage
}
from
'
vs/base/common/errorMessage
'
;
import
{
isPromiseCanceledError
}
from
'
vs/base/common/errors
'
;
import
*
as
glob
from
'
vs/base/common/glob
'
;
import
{
toDisposable
}
from
'
vs/base/common/lifecycle
'
;
import
*
as
resources
from
'
vs/base/common/resources
'
;
...
...
@@ -82,30 +81,14 @@ export class ExtHostSearch implements ExtHostSearchShape {
const
provider
=
this
.
_fileSearchProvider
.
get
(
handle
);
const
query
=
reviveQuery
(
rawQuery
);
if
(
provider
)
{
return
new
Promise
((
c
,
e
)
=>
{
this
.
_fileSearchManager
.
fileSearch
(
query
,
provider
,
batch
=>
{
this
.
_proxy
.
$handleFileMatch
(
handle
,
session
,
batch
.
map
(
p
=>
p
.
resource
));
},
token
).
then
(
c
,
err
=>
{
if
(
!
isPromiseCanceledError
(
err
))
{
e
(
err
);
}
});
});
return
this
.
_fileSearchManager
.
fileSearch
(
query
,
provider
,
batch
=>
{
this
.
_proxy
.
$handleFileMatch
(
handle
,
session
,
batch
.
map
(
p
=>
p
.
resource
));
},
token
);
}
else
{
const
indexProvider
=
this
.
_fileIndexProvider
.
get
(
handle
);
const
searchP
=
this
.
_fileIndexSearchManager
.
fileSearch
(
query
,
indexProvider
,
batch
=>
{
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
;
});
token
.
onCancellationRequested
(()
=>
searchP
.
cancel
());
return
searchP
;
},
token
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录