Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
4fb54744
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,发现更多精彩内容 >>
提交
4fb54744
编写于
4月 29, 2020
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
renames
上级
3f30b1d5
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
109 addition
and
101 deletion
+109
-101
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder.cs
...ortable/FindSymbols/FindReferences/DependentTypeFinder.cs
+109
-101
未找到文件。
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder.cs
浏览文件 @
4fb54744
...
...
@@ -46,8 +46,7 @@ internal static partial class DependentTypeFinder
private
static
readonly
Func
<
INamedTypeSymbol
,
bool
>
s_isNonSealedClass
=
t
=>
t
?.
TypeKind
==
TypeKind
.
Class
&&
!
t
.
IsSealed
;
private
static
readonly
Func
<
INamedTypeSymbol
,
bool
>
s_isInterfaceOrNonSealedClass
=
t
=>
s_isInterface
(
t
)
||
s_isNonSealedClass
(
t
);
private
static
readonly
ObjectPool
<
SymbolSet
>
s_setPool
=
new
ObjectPool
<
SymbolSet
>(
()
=>
new
SymbolSet
(
SymbolEquivalenceComparer
.
Instance
));
private
static
readonly
ObjectPool
<
PooledHashSet
<
INamedTypeSymbol
>>
s_setPool1
=
PooledHashSet
<
INamedTypeSymbol
>.
CreatePool
(
SymbolEquivalenceComparer
.
Instance
);
// Caches from a types to their related types (in the context of a specific solution).
// Kept as a cache so that clients who make many calls into us won't end up computing
...
...
@@ -194,16 +193,20 @@ internal static partial class DependentTypeFinder
var
orderedProjectsToExamine
=
GetOrderedProjectsToExamine
(
solution
,
projects
,
projectsThatCouldReferenceType
);
var
currentMetadataTypes
=
CreateSymbolAndProjectIdSet
();
var
currentSourceAndMetadataTypes
=
CreateSymbolAndProjectIdSet
();
// The final set of results we'll be returning.
using
var
_1
=
GetSymbolSet
(
out
var
result
);
// The current total set of matching metadata types in the descendant tree (including the initial type if it
// is from metadata). Will be used when examining new types to see if they inherit from any of htese.
using
var
_2
=
GetSymbolSet
(
out
var
currentMetadataTypes
);
// Same as above, but contains source types as well.
using
var
_3
=
GetSymbolSet
(
out
var
currentSourceAndMetadataTypes
);
currentSourceAndMetadataTypes
.
Add
(
type
);
if
(
searchInMetadata
)
{
currentMetadataTypes
.
Add
(
type
);
}
var
result
=
CreateSymbolAndProjectIdSet
();
// Now walk the projects from left to right seeing what our type cascades to. Once we
// reach a fixed point in that project, take all the types we've found and move to the
...
...
@@ -226,15 +229,7 @@ internal static partial class DependentTypeFinder
transitive
,
cancellationToken
).
ConfigureAwait
(
false
);
}
return
ToImmutableAndFree
(
result
);
}
private
static
ImmutableArray
<
INamedTypeSymbol
>
ToImmutableAndFree
(
SymbolSet
set
)
{
var
array
=
set
.
ToImmutableArray
();
s_setPool
.
ClearAndFree
(
set
);
return
array
;
return
result
.
ToImmutableArray
();
}
private
static
async
Task
DescendInheritanceTreeInProjectAsync
(
...
...
@@ -252,65 +247,59 @@ internal static partial class DependentTypeFinder
Debug
.
Assert
(
project
.
SupportsCompilation
);
var
foundTypes
=
CreateSymbolAndProjectIdSet
();
try
{
// First see what derived metadata types we might find in this project. This is only necessary if we
// started with a metadata type (i.e. a source type could not have a descendant type found in metadata,
// but a metadata type could have descendant types in source and metadata).
if
(
searchInMetadata
)
{
await
AddDescendantMetadataTypesInProjectAsync
(
currentMetadataTypes
,
project
,
typeMatches
,
shouldContinueSearching
,
transitive
,
foundTypes
,
cancellationToken
).
ConfigureAwait
(
false
);
using
var
_
=
GetSymbolSet
(
out
var
tempBuffer
);
// Add all the matches we found to the result set.
AssertContents
(
foundTypes
,
assert
:
s_isInMetadata
,
"Found type was not from metadata"
);
AddRange
(
foundTypes
,
result
);
// First see what derived metadata types we might find in this project. This is only necessary if we
// started with a metadata type (i.e. a source type could not have a descendant type found in metadata,
// but a metadata type could have descendant types in source and metadata).
if
(
searchInMetadata
)
{
await
AddDescendantMetadataTypesInProjectAsync
(
currentMetadataTypes
,
result
:
tempBuffer
,
project
,
typeMatches
,
shouldContinueSearching
,
transitive
,
cancellationToken
).
ConfigureAwait
(
false
);
// Now, if we're doing a transitive search, add these found types to the 'current' sets we're
// searching for more results for. These will then be used when searching for more types in the next
// project (which our caller controls).
if
(
transitive
)
{
AddRange
(
foundTypes
,
currentMetadataTypes
,
shouldContinueSearching
);
AddRange
(
foundTypes
,
currentSourceAndMetadataTypes
,
shouldContinueSearching
);
}
}
// Add all the matches we found to the result set.
AssertContents
(
tempBuffer
,
assert
:
s_isInMetadata
,
"Found type was not from metadata"
);
AddRange
(
tempBuffer
,
result
);
// Now, if we're doing a transitive search, add these found types to the 'current' sets we're
// searching for more results for. These will then be used when searching for more types in the next
// project (which our caller controls).
if
(
transitive
)
{
// Now search the project and see what source types we can find.
foundTypes
.
Clear
();
await
AddDescendantSourceTypesInProjectAsync
(
currentSourceAndMetadataTypes
,
project
,
typeMatches
,
shouldContinueSearching
,
transitive
,
foundTypes
,
cancellationToken
).
ConfigureAwait
(
false
);
// Add all the matches we found to the result set.
AssertContents
(
foundTypes
,
assert
:
s_isInSource
,
"Found type was not from source"
);
AddRange
(
foundTypes
,
result
);
// Now, if we're doing a transitive search, add these types to the currentSourceAndMetadataTypes
// set. These will then be used when searching for more types in the next project (which our caller
// controls). We don't have to add this to currentMetadataTypes since these will all be
// source types.
if
(
transitive
)
AddRange
(
foundTypes
,
currentSourceAndMetadataTypes
,
shouldContinueSearching
);
AddRange
(
tempBuffer
,
currentMetadataTypes
,
shouldContinueSearching
);
AddRange
(
tempBuffer
,
currentSourceAndMetadataTypes
,
shouldContinueSearching
);
}
}
finally
{
s_setPool
.
ClearAndFree
(
foundTypes
);
tempBuffer
.
Clear
();
// Now search the project and see what source types we can find.
await
AddDescendantSourceTypesInProjectAsync
(
currentSourceAndMetadataTypes
,
result
:
tempBuffer
,
project
,
typeMatches
,
shouldContinueSearching
,
transitive
,
cancellationToken
).
ConfigureAwait
(
false
);
// Add all the matches we found to the result set.
AssertContents
(
tempBuffer
,
assert
:
s_isInSource
,
"Found type was not from source"
);
AddRange
(
tempBuffer
,
result
);
// Now, if we're doing a transitive search, add these types to the currentSourceAndMetadataTypes
// set. These will then be used when searching for more types in the next project (which our caller
// controls). We don't have to add this to currentMetadataTypes since these will all be
// source types.
if
(
transitive
)
AddRange
(
tempBuffer
,
currentSourceAndMetadataTypes
,
shouldContinueSearching
);
}
}
...
...
@@ -460,11 +449,11 @@ private static void AddRange(SymbolSet foundTypes, SymbolSet result)
private
static
async
Task
AddDescendantMetadataTypesInProjectAsync
(
SymbolSet
metadataTypes
,
SymbolSet
result
,
Project
project
,
Func
<
INamedTypeSymbol
,
SymbolSet
,
bool
>
metadataTypeMatches
,
Func
<
INamedTypeSymbol
,
bool
>
shouldContinueSearching
,
bool
transitive
,
SymbolSet
result
,
CancellationToken
cancellationToken
)
{
Debug
.
Assert
(
project
.
SupportsCompilation
);
...
...
@@ -474,23 +463,23 @@ private static void AddRange(SymbolSet foundTypes, SymbolSet result)
var
compilation
=
await
project
.
GetCompilationAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
typesToSearchFor
=
CreateSymbolAndProjectIdSet
(
);
typesToSearchFor
.
AddAll
(
metadataTypes
);
using
var
_1
=
GetSymbolSet
(
out
var
typesToSearchFor
);
using
var
_2
=
GetSymbolSet
(
out
var
tempBuffer
);
var
localBuffer
=
CreateSymbolAndProjectIdSet
(
);
typesToSearchFor
.
AddAll
(
metadataTypes
);
// As long as there are new types to search for, keep looping.
while
(
typesToSearchFor
.
Count
>
0
)
{
local
Buffer
.
Clear
();
temp
Buffer
.
Clear
();
foreach
(
var
reference
in
compilation
.
References
.
OfType
<
PortableExecutableReference
>())
{
cancellationToken
.
ThrowIfCancellationRequested
();
await
FindImmediate
MatchingMetadataTypesInMetadataReferenceAsync
(
await
Add
MatchingMetadataTypesInMetadataReferenceAsync
(
typesToSearchFor
,
project
,
metadataTypeMatches
,
compilation
,
reference
,
local
Buffer
,
compilation
,
reference
,
temp
Buffer
,
cancellationToken
).
ConfigureAwait
(
false
);
}
...
...
@@ -499,7 +488,7 @@ private static void AddRange(SymbolSet foundTypes, SymbolSet result)
// for.
typesToSearchFor
.
Clear
();
foreach
(
var
derivedType
in
local
Buffer
)
foreach
(
var
derivedType
in
temp
Buffer
)
{
if
(
result
.
Add
(
derivedType
))
{
...
...
@@ -510,7 +499,7 @@ private static void AddRange(SymbolSet foundTypes, SymbolSet result)
}
}
private
static
async
Task
FindImmediate
MatchingMetadataTypesInMetadataReferenceAsync
(
private
static
async
Task
Add
MatchingMetadataTypesInMetadataReferenceAsync
(
SymbolSet
metadataTypes
,
Project
project
,
Func
<
INamedTypeSymbol
,
SymbolSet
,
bool
>
metadataTypeTransitivelyMatches
,
...
...
@@ -568,11 +557,11 @@ private static bool TypeHasInterfaceInSet(INamedTypeSymbol type, SymbolSet set)
private
static
async
Task
AddDescendantSourceTypesInProjectAsync
(
SymbolSet
sourceAndMetadataTypes
,
SymbolSet
result
,
Project
project
,
Func
<
INamedTypeSymbol
,
SymbolSet
,
bool
>
sourceTypeMatches
,
Func
<
INamedTypeSymbol
,
bool
>
shouldContinueSearching
,
bool
transitive
,
SymbolSet
finalResult
,
CancellationToken
cancellationToken
)
{
cancellationToken
.
ThrowIfCancellationRequested
();
...
...
@@ -583,17 +572,17 @@ private static bool TypeHasInterfaceInSet(INamedTypeSymbol type, SymbolSet set)
// Because we're only processing a project at a time, this is not an issue.
var
cachedModels
=
new
ConcurrentSet
<
SemanticModel
>();
var
typesToSearchFor
=
CreateSymbolAndProjectIdSet
();
using
var
_1
=
GetSymbolSet
(
out
var
typesToSearchFor
);
using
var
_2
=
GetSymbolSet
(
out
var
tempBuffer
);
typesToSearchFor
.
AddAll
(
sourceAndMetadataTypes
);
var
projectIndex
=
await
ProjectIndex
.
GetIndexAsync
(
project
,
cancellationToken
).
ConfigureAwait
(
false
);
var
localBuffer
=
CreateSymbolAndProjectIdSet
();
// As long as there are new types to search for, keep looping.
while
(
typesToSearchFor
.
Count
>
0
)
{
local
Buffer
.
Clear
();
temp
Buffer
.
Clear
();
foreach
(
var
type
in
typesToSearchFor
)
{
...
...
@@ -603,30 +592,46 @@ private static bool TypeHasInterfaceInSet(INamedTypeSymbol type, SymbolSet set)
{
case
SpecialType
.
System_Object
:
await
AddMatchingTypesAsync
(
cachedModels
,
projectIndex
.
ClassesThatMayDeriveFromSystemObject
,
localBuffer
,
cachedModels
,
projectIndex
.
ClassesThatMayDeriveFromSystemObject
,
result
:
tempBuffer
,
predicateOpt
:
n
=>
n
.
BaseType
?.
SpecialType
==
SpecialType
.
System_Object
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
cancellationToken
).
ConfigureAwait
(
false
);
break
;
case
SpecialType
.
System_ValueType
:
await
AddMatchingTypesAsync
(
cachedModels
,
projectIndex
.
ValueTypes
,
localBuffer
,
predicateOpt
:
null
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
cachedModels
,
projectIndex
.
ValueTypes
,
result
:
tempBuffer
,
predicateOpt
:
null
,
cancellationToken
).
ConfigureAwait
(
false
);
break
;
case
SpecialType
.
System_Enum
:
await
AddMatchingTypesAsync
(
cachedModels
,
projectIndex
.
Enums
,
localBuffer
,
predicateOpt
:
null
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
cachedModels
,
projectIndex
.
Enums
,
result
:
tempBuffer
,
predicateOpt
:
null
,
cancellationToken
).
ConfigureAwait
(
false
);
break
;
case
SpecialType
.
System_MulticastDelegate
:
await
AddMatchingTypesAsync
(
cachedModels
,
projectIndex
.
Delegates
,
localBuffer
,
predicateOpt
:
null
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
cachedModels
,
projectIndex
.
Delegates
,
result
:
tempBuffer
,
predicateOpt
:
null
,
cancellationToken
).
ConfigureAwait
(
false
);
break
;
}
await
AddTypesThatDeriveFromNameAsync
(
sourceTypeMatches
,
cachedModels
,
typesToSearchFor
,
projectIndex
,
localBuffer
,
type
.
Name
,
cancellationToken
).
ConfigureAwait
(
false
);
await
AddSourceTypesThatDeriveFromNameAsync
(
sourceTypeMatches
,
cachedModels
,
typesToSearchFor
,
projectIndex
,
result
:
tempBuffer
,
type
.
Name
,
cancellationToken
).
ConfigureAwait
(
false
);
}
// Clear out the information about the types we're looking for. We'll
...
...
@@ -634,20 +639,18 @@ private static bool TypeHasInterfaceInSet(INamedTypeSymbol type, SymbolSet set)
// for.
typesToSearchFor
.
Clear
();
foreach
(
var
derivedType
in
local
Buffer
)
foreach
(
var
derivedType
in
temp
Buffer
)
{
if
(
finalR
esult
.
Add
(
derivedType
))
if
(
r
esult
.
Add
(
derivedType
))
{
if
(
transitive
&&
shouldContinueSearching
(
derivedType
))
typesToSearchFor
.
Add
(
derivedType
);
}
}
}
s_setPool
.
ClearAndFree
(
localBuffer
);
}
private
static
async
Task
AddTypesThatDeriveFromNameAsync
(
private
static
async
Task
Add
Source
TypesThatDeriveFromNameAsync
(
Func
<
INamedTypeSymbol
,
SymbolSet
,
bool
>
sourceTypeMatches
,
ConcurrentSet
<
SemanticModel
>
cachedModels
,
SymbolSet
typesToSearchFor
,
...
...
@@ -704,8 +707,13 @@ private static bool TypeHasInterfaceInSet(INamedTypeSymbol type, SymbolSet set)
}
}
private
static
SymbolSet
CreateSymbolAndProjectIdSet
()
=>
s_setPool
.
Allocate
();
public
static
PooledDisposer
<
PooledHashSet
<
INamedTypeSymbol
>>
GetSymbolSet
(
out
SymbolSet
instance
)
{
var
pooledInstance
=
s_setPool1
.
Allocate
();
Debug
.
Assert
(
pooledInstance
.
Count
==
0
);
instance
=
pooledInstance
;
return
new
PooledDisposer
<
PooledHashSet
<
INamedTypeSymbol
>>(
pooledInstance
);
}
private
class
KeyEqualityComparer
:
IEqualityComparer
<(
SymbolKey
,
ProjectId
,
IImmutableSet
<
Project
>)>
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录