Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
cc06ed02
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
cc06ed02
编写于
1月 20, 2016
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Search projects in parallel. Cancel any parallel work once enough results are found.
上级
7af7a8a8
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
106 addition
and
64 deletion
+106
-64
src/Features/Core/Portable/CodeFixes/AddImport/AbstractAddImportCodeFixProvider.SearchScope.cs
...AddImport/AbstractAddImportCodeFixProvider.SearchScope.cs
+8
-8
src/Features/Core/Portable/CodeFixes/AddImport/AbstractAddImportCodeFixProvider.SymbolReferenceFinder.cs
...AbstractAddImportCodeFixProvider.SymbolReferenceFinder.cs
+36
-22
src/Features/Core/Portable/CodeFixes/AddImport/AbstractAddImportCodeFixProvider.cs
...e/CodeFixes/AddImport/AbstractAddImportCodeFixProvider.cs
+62
-34
未找到文件。
src/Features/Core/Portable/CodeFixes/AddImport/AbstractAddImportCodeFixProvider.SearchScope.cs
浏览文件 @
cc06ed02
...
...
@@ -26,12 +26,12 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
private
abstract
class
SearchScope
{
public
readonly
bool
Exact
;
p
rotected
readonly
CancellationToken
c
ancellationToken
;
p
ublic
readonly
CancellationToken
C
ancellationToken
;
protected
SearchScope
(
bool
exact
,
CancellationToken
cancellationToken
)
{
this
.
Exact
=
exact
;
this
.
c
ancellationToken
=
cancellationToken
;
Exact
=
exact
;
C
ancellationToken
=
cancellationToken
;
}
protected
abstract
Task
<
IEnumerable
<
ISymbol
>>
FindDeclarationsAsync
(
string
name
,
SymbolFilter
filter
,
SearchQuery
query
);
...
...
@@ -102,7 +102,7 @@ public AllSymbolsProjectSearchScope(Project project, bool ignoreCase, Cancellati
protected
override
Task
<
IEnumerable
<
ISymbol
>>
FindDeclarationsAsync
(
string
name
,
SymbolFilter
filter
,
SearchQuery
searchQuery
)
{
return
SymbolFinder
.
FindDeclarationsAsync
(
_project
,
searchQuery
,
filter
,
c
ancellationToken
);
return
SymbolFinder
.
FindDeclarationsAsync
(
_project
,
searchQuery
,
filter
,
C
ancellationToken
);
}
}
...
...
@@ -125,7 +125,7 @@ private class SourceSymbolsProjectSearchScope : ProjectSearchScope
protected
override
async
Task
<
IEnumerable
<
ISymbol
>>
FindDeclarationsAsync
(
string
name
,
SymbolFilter
filter
,
SearchQuery
searchQuery
)
{
var
service
=
_project
.
Solution
.
Workspace
.
Services
.
GetService
<
ISymbolTreeInfoCacheService
>();
var
info
=
await
service
.
TryGetSymbolTreeInfoAsync
(
_project
,
c
ancellationToken
).
ConfigureAwait
(
false
);
var
info
=
await
service
.
TryGetSymbolTreeInfoAsync
(
_project
,
C
ancellationToken
).
ConfigureAwait
(
false
);
if
(
info
==
null
)
{
// Looks like there was nothing in the cache. Return no results for now.
...
...
@@ -137,7 +137,7 @@ protected override async Task<IEnumerable<ISymbol>> FindDeclarationsAsync(string
// needed.
var
lazyAssembly
=
_projectToAssembly
.
GetOrAdd
(
_project
,
CreateLazyAssembly
);
return
await
info
.
FindAsync
(
searchQuery
,
lazyAssembly
,
c
ancellationToken
).
ConfigureAwait
(
false
);
return
await
info
.
FindAsync
(
searchQuery
,
lazyAssembly
,
C
ancellationToken
).
ConfigureAwait
(
false
);
}
private
static
AsyncLazy
<
IAssemblySymbol
>
CreateLazyAssembly
(
Project
project
)
...
...
@@ -180,13 +180,13 @@ public override SymbolReference CreateReference<T>(SearchResult<T> searchResult)
protected
override
async
Task
<
IEnumerable
<
ISymbol
>>
FindDeclarationsAsync
(
string
name
,
SymbolFilter
filter
,
SearchQuery
searchQuery
)
{
var
service
=
_solution
.
Workspace
.
Services
.
GetService
<
ISymbolTreeInfoCacheService
>();
var
info
=
await
service
.
TryGetSymbolTreeInfoAsync
(
_solution
,
_assembly
,
_metadataReference
,
c
ancellationToken
).
ConfigureAwait
(
false
);
var
info
=
await
service
.
TryGetSymbolTreeInfoAsync
(
_solution
,
_assembly
,
_metadataReference
,
C
ancellationToken
).
ConfigureAwait
(
false
);
if
(
info
==
null
)
{
return
SpecializedCollections
.
EmptyEnumerable
<
ISymbol
>();
}
return
await
info
.
FindAsync
(
searchQuery
,
_assembly
,
c
ancellationToken
).
ConfigureAwait
(
false
);
return
await
info
.
FindAsync
(
searchQuery
,
_assembly
,
C
ancellationToken
).
ConfigureAwait
(
false
);
}
}
}
...
...
src/Features/Core/Portable/CodeFixes/AddImport/AbstractAddImportCodeFixProvider.SymbolReferenceFinder.cs
浏览文件 @
cc06ed02
...
...
@@ -15,7 +15,6 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
{
private
class
SymbolReferenceFinder
{
private
readonly
CancellationToken
_cancellationToken
;
private
readonly
Diagnostic
_diagnostic
;
private
readonly
Document
_document
;
private
readonly
SemanticModel
_semanticModel
;
...
...
@@ -37,7 +36,6 @@ private class SymbolReferenceFinder
_semanticModel
=
semanticModel
;
_diagnostic
=
diagnostic
;
_node
=
node
;
_cancellationToken
=
cancellationToken
;
_containingType
=
semanticModel
.
GetEnclosingNamedType
(
node
.
SpanStart
,
cancellationToken
);
_containingTypeOrAssembly
=
_containingType
??
(
ISymbol
)
semanticModel
.
Compilation
.
Assembly
;
...
...
@@ -46,29 +44,31 @@ private class SymbolReferenceFinder
}
internal
Task
<
List
<
SymbolReference
>>
FindInAllProjectSymbolsAsync
(
Project
project
,
bool
exact
)
Project
project
,
bool
exact
,
CancellationToken
cancellationToken
)
{
var
searchScope
=
new
AllSymbolsProjectSearchScope
(
project
,
exact
,
_
cancellationToken
);
var
searchScope
=
new
AllSymbolsProjectSearchScope
(
project
,
exact
,
cancellationToken
);
return
DoAsync
(
searchScope
);
}
internal
Task
<
List
<
SymbolReference
>>
FindInSourceProjectSymbolsAsync
(
ConcurrentDictionary
<
Project
,
AsyncLazy
<
IAssemblySymbol
>>
projectToAssembly
,
Project
project
,
bool
exact
)
Project
project
,
bool
exact
,
CancellationToken
cancellationToken
)
{
var
searchScope
=
new
SourceSymbolsProjectSearchScope
(
projectToAssembly
,
project
,
exact
,
_
cancellationToken
);
var
searchScope
=
new
SourceSymbolsProjectSearchScope
(
projectToAssembly
,
project
,
exact
,
cancellationToken
);
return
DoAsync
(
searchScope
);
}
internal
Task
<
List
<
SymbolReference
>>
FindInMetadataAsync
(
Solution
solution
,
IAssemblySymbol
assembly
,
PortableExecutableReference
metadataReference
,
bool
exact
)
Solution
solution
,
IAssemblySymbol
assembly
,
PortableExecutableReference
metadataReference
,
bool
exact
,
CancellationToken
cancellationToken
)
{
var
searchScope
=
new
MetadataSymbolsSearchScope
(
solution
,
assembly
,
metadataReference
,
exact
,
_
cancellationToken
);
var
searchScope
=
new
MetadataSymbolsSearchScope
(
solution
,
assembly
,
metadataReference
,
exact
,
cancellationToken
);
return
DoAsync
(
searchScope
);
}
private
async
Task
<
List
<
SymbolReference
>>
DoAsync
(
SearchScope
searchScope
)
{
searchScope
.
CancellationToken
.
ThrowIfCancellationRequested
();
// Spin off tasks to do all our searching.
var
tasks
=
new
List
<
Task
<
IList
<
SymbolReference
>>>
{
...
...
@@ -92,7 +92,7 @@ private async Task<List<SymbolReference>> DoAsync(SearchScope searchScope)
}
await
Task
.
WhenAll
(
tasks
).
ConfigureAwait
(
false
);
_c
ancellationToken
.
ThrowIfCancellationRequested
();
searchScope
.
C
ancellationToken
.
ThrowIfCancellationRequested
();
List
<
SymbolReference
>
allReferences
=
null
;
foreach
(
var
task
in
tasks
)
...
...
@@ -125,6 +125,8 @@ private List<SymbolReference> DeDupeAndSortReferences(List<SymbolReference> allR
private
async
Task
<
IList
<
SymbolReference
>>
GetNamespacesForMatchingTypesAsync
(
SearchScope
searchScope
)
{
searchScope
.
CancellationToken
.
ThrowIfCancellationRequested
();
TSimpleNameSyntax
nameNode
;
if
(!
_owner
.
CanAddImportForType
(
_diagnostic
,
_node
,
out
nameNode
))
{
...
...
@@ -147,6 +149,8 @@ private async Task<IList<SymbolReference>> GetNamespacesForMatchingTypesAsync(Se
private
async
Task
<
IList
<
SymbolReference
>>
GetMatchingTypesAsync
(
SearchScope
searchScope
)
{
searchScope
.
CancellationToken
.
ThrowIfCancellationRequested
();
TSimpleNameSyntax
nameNode
;
if
(!
_owner
.
CanAddImportForType
(
_diagnostic
,
_node
,
out
nameNode
))
{
...
...
@@ -173,12 +177,12 @@ private async Task<IList<SymbolReference>> GetMatchingTypesAsync(SearchScope sea
TSimpleNameSyntax
nameNode
,
bool
inAttributeContext
)
{
if
(
_c
ancellationToken
.
IsCancellationRequested
)
if
(
searchScope
.
C
ancellationToken
.
IsCancellationRequested
)
{
return
null
;
}
if
(
ExpressionBinds
(
nameNode
,
checkForExtensionMethods
:
false
))
if
(
ExpressionBinds
(
searchScope
,
nameNode
,
checkForExtensionMethods
:
false
))
{
return
null
;
}
...
...
@@ -197,12 +201,12 @@ private async Task<IList<SymbolReference>> GetMatchingTypesAsync(SearchScope sea
return
OfType
<
ITypeSymbol
>(
symbols
);
}
protected
bool
ExpressionBinds
(
TSimpleNameSyntax
nameNode
,
bool
checkForExtensionMethods
)
protected
bool
ExpressionBinds
(
SearchScope
searchScope
,
TSimpleNameSyntax
nameNode
,
bool
checkForExtensionMethods
)
{
// See if the name binds to something other then the error type. If it does, there's nothing further we need to do.
// For extension methods, however, we will continue to search if there exists any better matched method.
_c
ancellationToken
.
ThrowIfCancellationRequested
();
var
symbolInfo
=
_semanticModel
.
GetSymbolInfo
(
nameNode
,
_c
ancellationToken
);
searchScope
.
C
ancellationToken
.
ThrowIfCancellationRequested
();
var
symbolInfo
=
_semanticModel
.
GetSymbolInfo
(
nameNode
,
searchScope
.
C
ancellationToken
);
if
(
symbolInfo
.
CandidateReason
==
CandidateReason
.
OverloadResolutionFailure
&&
!
checkForExtensionMethods
)
{
return
true
;
...
...
@@ -214,6 +218,8 @@ protected bool ExpressionBinds(TSimpleNameSyntax nameNode, bool checkForExtensio
private
async
Task
<
IList
<
SymbolReference
>>
GetNamespacesForMatchingNamespacesAsync
(
SearchScope
searchScope
)
{
searchScope
.
CancellationToken
.
ThrowIfCancellationRequested
();
TSimpleNameSyntax
nameNode
;
if
(!
_owner
.
CanAddImportForNamespace
(
_diagnostic
,
_node
,
out
nameNode
))
{
...
...
@@ -229,7 +235,7 @@ protected bool ExpressionBinds(TSimpleNameSyntax nameNode, bool checkForExtensio
return
null
;
}
if
(
ExpressionBinds
(
nameNode
,
checkForExtensionMethods
:
false
))
if
(
ExpressionBinds
(
searchScope
,
nameNode
,
checkForExtensionMethods
:
false
))
{
return
null
;
}
...
...
@@ -242,6 +248,8 @@ protected bool ExpressionBinds(TSimpleNameSyntax nameNode, bool checkForExtensio
private
async
Task
<
IList
<
SymbolReference
>>
GetNamespacesForMatchingExtensionMethodsAsync
(
SearchScope
searchScope
)
{
searchScope
.
CancellationToken
.
ThrowIfCancellationRequested
();
TSimpleNameSyntax
nameNode
;
if
(!
_owner
.
CanAddImportForMethod
(
_diagnostic
,
_syntaxFacts
,
_node
,
out
nameNode
))
{
...
...
@@ -261,6 +269,8 @@ private async Task<IList<SymbolReference>> GetNamespacesForMatchingExtensionMeth
private
async
Task
<
IList
<
SymbolReference
>>
GetNamespacesForCollectionInitializerMethodsAsync
(
SearchScope
searchScope
)
{
searchScope
.
CancellationToken
.
ThrowIfCancellationRequested
();
TSimpleNameSyntax
nameNode
;
if
(!
_owner
.
CanAddImportForMethod
(
_diagnostic
,
_syntaxFacts
,
_node
,
out
nameNode
))
{
...
...
@@ -274,6 +284,8 @@ private async Task<IList<SymbolReference>> GetNamespacesForCollectionInitializer
private
async
Task
<
IList
<
SymbolReference
>>
GetNamespacesForMatchingFieldsAndPropertiesAsync
(
SearchScope
searchScope
)
{
searchScope
.
CancellationToken
.
ThrowIfCancellationRequested
();
TSimpleNameSyntax
nameNode
;
if
(!
_owner
.
CanAddImportForMethod
(
_diagnostic
,
_syntaxFacts
,
_node
,
out
nameNode
))
{
...
...
@@ -296,12 +308,14 @@ private async Task<IList<SymbolReference>> GetNamespacesForCollectionInitializer
private
async
Task
<
IList
<
SymbolReference
>>
GetNamespacesForQueryPatternsAsync
(
SearchScope
searchScope
)
{
searchScope
.
CancellationToken
.
ThrowIfCancellationRequested
();
if
(!
_owner
.
CanAddImportForQuery
(
_diagnostic
,
_node
))
{
return
null
;
}
ITypeSymbol
type
=
_owner
.
GetQueryClauseInfo
(
_semanticModel
,
_node
,
_c
ancellationToken
);
ITypeSymbol
type
=
_owner
.
GetQueryClauseInfo
(
_semanticModel
,
_node
,
searchScope
.
C
ancellationToken
);
if
(
type
==
null
)
{
return
null
;
...
...
@@ -380,10 +394,10 @@ private List<SymbolReference> GetProposedTypes(SearchScope searchScope, string n
private
Task
<
IEnumerable
<
SearchResult
<
ISymbol
>>>
GetSymbolsAsync
(
SearchScope
searchScope
,
TSimpleNameSyntax
nameNode
)
{
_c
ancellationToken
.
ThrowIfCancellationRequested
();
searchScope
.
C
ancellationToken
.
ThrowIfCancellationRequested
();
// See if the name binds. If it does, there's nothing further we need to do.
if
(
ExpressionBinds
(
nameNode
,
checkForExtensionMethods
:
true
))
if
(
ExpressionBinds
(
searchScope
,
nameNode
,
checkForExtensionMethods
:
true
))
{
return
SpecializedTasks
.
EmptyEnumerable
<
SearchResult
<
ISymbol
>>();
}
...
...
@@ -405,7 +419,7 @@ private Task<IEnumerable<SearchResult<ISymbol>>> GetSymbolsAsync(SearchScope sea
var
extensionMethodSymbols
=
OfType
<
IMethodSymbol
>(
symbols
)
.
Where
(
s
=>
s
.
Symbol
.
IsExtensionMethod
&&
s
.
Symbol
.
IsAccessibleWithin
(
_semanticModel
.
Compilation
.
Assembly
)
==
true
&&
_owner
.
IsViableExtensionMethod
(
s
.
Symbol
,
expression
,
_semanticModel
,
_syntaxFacts
,
_c
ancellationToken
))
_owner
.
IsViableExtensionMethod
(
s
.
Symbol
,
expression
,
_semanticModel
,
_syntaxFacts
,
searchScope
.
C
ancellationToken
))
.
ToList
();
return
GetProposedNamespaces
(
...
...
@@ -417,12 +431,12 @@ private Task<IEnumerable<SearchResult<ISymbol>>> GetSymbolsAsync(SearchScope sea
{
var
propertySymbols
=
OfType
<
IPropertySymbol
>(
symbols
)
.
Where
(
property
=>
property
.
Symbol
.
IsAccessibleWithin
(
_semanticModel
.
Compilation
.
Assembly
)
==
true
&&
_owner
.
IsViableProperty
(
property
.
Symbol
,
expression
,
_semanticModel
,
_syntaxFacts
,
_c
ancellationToken
))
_owner
.
IsViableProperty
(
property
.
Symbol
,
expression
,
_semanticModel
,
_syntaxFacts
,
searchScope
.
C
ancellationToken
))
.
ToList
();
var
fieldSymbols
=
OfType
<
IFieldSymbol
>(
symbols
)
.
Where
(
field
=>
field
.
Symbol
.
IsAccessibleWithin
(
_semanticModel
.
Compilation
.
Assembly
)
==
true
&&
_owner
.
IsViableField
(
field
.
Symbol
,
expression
,
_semanticModel
,
_syntaxFacts
,
_c
ancellationToken
))
_owner
.
IsViableField
(
field
.
Symbol
,
expression
,
_semanticModel
,
_syntaxFacts
,
searchScope
.
C
ancellationToken
))
.
ToList
();
return
GetProposedNamespaces
(
...
...
@@ -449,7 +463,7 @@ private Task<IEnumerable<SearchResult<ISymbol>>> GetSymbolsAsync(SearchScope sea
return
OfType
<
IMethodSymbol
>(
symbols
)
.
Where
(
s
=>
s
.
Symbol
.
IsExtensionMethod
&&
s
.
Symbol
.
IsAccessibleWithin
(
_semanticModel
.
Compilation
.
Assembly
)
==
true
&&
_owner
.
IsViableExtensionMethod
(
s
.
Symbol
,
expression
,
_semanticModel
,
_syntaxFacts
,
_c
ancellationToken
))
_owner
.
IsViableExtensionMethod
(
s
.
Symbol
,
expression
,
_semanticModel
,
_syntaxFacts
,
searchScope
.
C
ancellationToken
))
.
Select
(
s
=>
s
.
WithDesiredName
(
null
));
}
...
...
src/Features/Core/Portable/CodeFixes/AddImport/AbstractAddImportCodeFixProvider.cs
浏览文件 @
cc06ed02
...
...
@@ -117,7 +117,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
// First search the current project to see if any symbols (source or metadata) match the
// search string.
await
FindResultsInAllProjectSymbolsAsync
(
project
,
allSymbolReferences
,
finder
,
exact
).
ConfigureAwait
(
false
);
await
FindResultsInAllProjectSymbolsAsync
(
project
,
allSymbolReferences
,
finder
,
exact
,
cancellationToken
).
ConfigureAwait
(
false
);
// Now search unreferenced projects, and see if they have any source symbols that match
// the search string.
...
...
@@ -128,9 +128,9 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
}
private
async
Task
FindResultsInAllProjectSymbolsAsync
(
Project
project
,
List
<
SymbolReference
>
allSymbolReferences
,
SymbolReferenceFinder
finder
,
bool
exact
)
Project
project
,
List
<
SymbolReference
>
allSymbolReferences
,
SymbolReferenceFinder
finder
,
bool
exact
,
CancellationToken
cancellationToken
)
{
var
references
=
await
finder
.
FindInAllProjectSymbolsAsync
(
project
,
exact
).
ConfigureAwait
(
false
);
var
references
=
await
finder
.
FindInAllProjectSymbolsAsync
(
project
,
exact
,
cancellationToken
).
ConfigureAwait
(
false
);
AddRange
(
allSymbolReferences
,
references
);
}
...
...
@@ -186,17 +186,25 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
}
var
viableUnreferencedProjects
=
GetViableUnreferencedProjects
(
project
);
foreach
(
var
unreferencedProject
in
viableUnreferencedProjects
)
// Search all unreferenced projects in parallel.
var
findTasks
=
new
HashSet
<
Task
<
List
<
SymbolReference
>>>();
// Create another cancellation token so we can both search all projects in parallel,
// but also stop any searches once we get enough results.
using
(
var
nestedTokenSource
=
new
CancellationTokenSource
())
using
(
var
linkedTokenSource
=
CancellationTokenSource
.
CreateLinkedTokenSource
(
nestedTokenSource
.
Token
,
cancellationToken
))
{
// Search in this unreferenced project. But don't search in any of its'
// direct references. i.e. we don't want to search in its metadata references
// or in the projects it references itself. We'll be searching those entities
// individually.
AddRange
(
allSymbolReferences
,
await
finder
.
FindInSourceProjectSymbolsAsync
(
projectToAssembly
,
unreferencedProject
,
exact
:
exact
).
ConfigureAwait
(
false
));
if
(
allSymbolReferences
.
Count
>=
MaxResults
)
foreach
(
var
unreferencedProject
in
viableUnreferencedProjects
)
{
return
;
// Search in this unreferenced project. But don't search in any of its'
// direct references. i.e. we don't want to search in its metadata references
// or in the projects it references itself. We'll be searching those entities
// individually.
findTasks
.
Add
(
finder
.
FindInSourceProjectSymbolsAsync
(
projectToAssembly
,
unreferencedProject
,
exact
,
linkedTokenSource
.
Token
));
}
await
WaitForTasksAsync
(
allSymbolReferences
,
findTasks
,
nestedTokenSource
,
cancellationToken
).
ConfigureAwait
(
false
);
}
}
...
...
@@ -228,40 +236,60 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
// Search all metadata references in parallel.
var
findTasks
=
new
HashSet
<
Task
<
List
<
SymbolReference
>>>();
foreach
(
var
reference
in
newReferences
)
// Create another cancellation token so we can both search all projects in parallel,
// but also stop any searches once we get enough results.
using
(
var
nestedTokenSource
=
new
CancellationTokenSource
())
using
(
var
linkedTokenSource
=
CancellationTokenSource
.
CreateLinkedTokenSource
(
nestedTokenSource
.
Token
,
cancellationToken
))
{
var
compilation
=
referenceToCompilation
.
GetOrAdd
(
reference
,
r
=>
CreateCompilation
(
project
,
r
));
// Ignore netmodules. First, they're incredibly esoteric and barely used.
// Second, the SymbolFinder api doesn't even support searching them.
var
assembly
=
compilation
.
GetAssemblyOrModuleSymbol
(
reference
)
as
IAssemblySymbol
;
if
(
assembly
!=
null
)
foreach
(
var
reference
in
newReferences
)
{
findTasks
.
Add
(
finder
.
FindInMetadataAsync
(
project
.
Solution
,
assembly
,
reference
,
exact
));
var
compilation
=
referenceToCompilation
.
GetOrAdd
(
reference
,
r
=>
CreateCompilation
(
project
,
r
));
// Ignore netmodules. First, they're incredibly esoteric and barely used.
// Second, the SymbolFinder api doesn't even support searching them.
var
assembly
=
compilation
.
GetAssemblyOrModuleSymbol
(
reference
)
as
IAssemblySymbol
;
if
(
assembly
!=
null
)
{
findTasks
.
Add
(
finder
.
FindInMetadataAsync
(
project
.
Solution
,
assembly
,
reference
,
exact
,
linkedTokenSource
.
Token
));
}
}
await
WaitForTasksAsync
(
allSymbolReferences
,
findTasks
,
nestedTokenSource
,
cancellationToken
).
ConfigureAwait
(
false
);
}
}
while
(
findTasks
.
Count
>
0
)
private
async
Task
WaitForTasksAsync
(
List
<
SymbolReference
>
allSymbolReferences
,
HashSet
<
Task
<
List
<
SymbolReference
>>>
findTasks
,
CancellationTokenSource
nestedTokenSource
,
CancellationToken
cancellationToken
)
{
try
{
// Keep on looping through the 'find' tasks, processing each when they finish.
cancellationToken
.
ThrowIfCancellationRequested
();
var
doneTask
=
await
Task
.
WhenAny
(
findTasks
).
ConfigureAwait
(
false
);
while
(
findTasks
.
Count
>
0
)
{
// Keep on looping through the 'find' tasks, processing each when they finish.
cancellationToken
.
ThrowIfCancellationRequested
();
var
doneTask
=
await
Task
.
WhenAny
(
findTasks
).
ConfigureAwait
(
false
);
// One of the tasks finished. Remove it from the list we're waiting on.
findTasks
.
Remove
(
doneTask
);
// One of the tasks finished. Remove it from the list we're waiting on.
findTasks
.
Remove
(
doneTask
);
// Add its results to the final result set we're keeping.
AddRange
(
allSymbolReferences
,
await
doneTask
.
ConfigureAwait
(
false
));
// Add its results to the final result set we're keeping.
AddRange
(
allSymbolReferences
,
await
doneTask
.
ConfigureAwait
(
false
));
// If we've got enough, no need to keep searching.
// Note: We do not cancel the existing tasks that are still executing. These tasks will
// cause our indices to be created if necessary. And that's good for future searches which
// we will invariably perform.
if
(
allSymbolReferences
.
Count
>=
MaxResults
)
{
break
;
// Once we get enough, just stop.
if
(
allSymbolReferences
.
Count
>=
MaxResults
)
{
return
;
}
}
}
finally
{
// Cancel any nested work that's still happening.
nestedTokenSource
.
Cancel
();
}
}
/// <summary>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录