Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
da62ba87
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,发现更多精彩内容 >>
未验证
提交
da62ba87
编写于
4月 30, 2020
作者:
C
CyrusNajmabadi
提交者:
GitHub
4月 30, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #43636 from CyrusNajmabadi/depTypeFinderOOP
Move dependent-type-finding operations out of process.
上级
ed503f4c
ed0b1982
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
437 addition
and
73 deletion
+437
-73
src/EditorFeatures/Test/SymbolFinder/DependentTypeFinderTests.cs
...torFeatures/Test/SymbolFinder/DependentTypeFinderTests.cs
+144
-37
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder.cs
...ortable/FindSymbols/FindReferences/DependentTypeFinder.cs
+25
-20
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder_DerivedClasses.cs
...bols/FindReferences/DependentTypeFinder_DerivedClasses.cs
+22
-4
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder_DerivedInterfaces.cs
...s/FindReferences/DependentTypeFinder_DerivedInterfaces.cs
+22
-1
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder_ImplementingTypes.cs
...s/FindReferences/DependentTypeFinder_ImplementingTypes.cs
+30
-8
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder_Remote.cs
.../FindSymbols/FindReferences/DependentTypeFinder_Remote.cs
+68
-0
src/Workspaces/Core/Portable/FindSymbols/FindReferences/IRemoteDependentTypeFinder.cs
.../FindSymbols/FindReferences/IRemoteDependentTypeFinder.cs
+35
-0
src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_DependentTypeFinder.cs
...ceHub/Services/CodeAnalysisService_DependentTypeFinder.cs
+84
-0
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs
...redUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs
+7
-3
未找到文件。
src/
Workspaces/CoreTest
/DependentTypeFinderTests.cs
→
src/
EditorFeatures/Test/SymbolFinder
/DependentTypeFinderTests.cs
浏览文件 @
da62ba87
...
...
@@ -4,19 +4,58 @@
using
System.Linq
;
using
System.Threading.Tasks
;
using
System.Xml.Linq
;
using
Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
;
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Test.Utilities
;
using
Microsoft.CodeAnalysis.Test.Utilities.RemoteHost
;
using
Microsoft.CodeAnalysis.Text
;
using
Roslyn.Test.Utilities
;
using
Xunit
;
namespace
Microsoft.CodeAnalysis.UnitTests
{
public
class
SymbolFinderTests
:
ServicesTestBase
public
enum
TestHost
{
[
Fact
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedTypes_CSharp
()
InProcess
,
OutOfProcess
,
}
[
UseExportProvider
]
public
class
SymbolFinderTests
:
TestBase
{
private
static
Solution
AddProjectWithMetadataReferences
(
Solution
solution
,
string
projectName
,
string
languageName
,
string
code
,
MetadataReference
metadataReference
,
params
ProjectId
[]
projectReferences
)
{
var
suffix
=
languageName
==
LanguageNames
.
CSharp
?
"cs"
:
"vb"
;
var
pid
=
ProjectId
.
CreateNewId
();
var
did
=
DocumentId
.
CreateNewId
(
pid
);
var
pi
=
ProjectInfo
.
Create
(
pid
,
VersionStamp
.
Default
,
projectName
,
projectName
,
languageName
,
metadataReferences
:
new
[]
{
metadataReference
},
projectReferences
:
projectReferences
.
Select
(
p
=>
new
ProjectReference
(
p
)));
return
solution
.
AddProject
(
pi
).
AddDocument
(
did
,
$"
{
projectName
}
.
{
suffix
}
"
,
SourceText
.
From
(
code
));
}
private
static
TestWorkspace
GetWorkspace
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
var
workspace
=
TestWorkspace
.
CreateWorkspace
(
XElement
.
Parse
(
"<Workspace></Workspace>"
));
workspace
.
TryApplyChanges
(
workspace
.
CurrentSolution
.
WithOptions
(
workspace
.
Options
.
WithChangedOption
(
RemoteHostOptions
.
RemoteHostTest
,
host
==
TestHost
.
OutOfProcess
)));
return
workspace
;
}
[
Theory
,
CombinatorialData
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedTypes_CSharp
(
TestHost
host
)
{
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create portable assembly with an abstract base class
solution
=
AddProjectWithMetadataReferences
(
solution
,
"PortableProject"
,
LanguageNames
.
CSharp
,
@"
...
...
@@ -53,10 +92,11 @@ public class DerivedClass : BaseClass { }
Assert
.
Equal
(
derivedClassSymbol
,
derivedDependentType
);
}
[
Fact
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedInterfaces_CSharp
()
[
Theory
,
CombinatorialData
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedInterfaces_CSharp
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create portable assembly with an abstract base class
solution
=
AddProjectWithMetadataReferences
(
solution
,
"PortableProject"
,
LanguageNames
.
CSharp
,
@"
...
...
@@ -99,10 +139,11 @@ private static Project GetPortableProject(Solution solution)
private
static
Project
GetNormalProject
(
Solution
solution
)
=>
solution
.
Projects
.
Single
(
p
=>
p
.
Name
==
"NormalProject"
);
[
Fact
]
public
async
Task
ImmediatelyDerivedTypes_CSharp_AliasedNames
()
[
Theory
,
CombinatorialData
]
public
async
Task
ImmediatelyDerivedTypes_CSharp_AliasedNames
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create portable assembly with an abstract base class
solution
=
AddProjectWithMetadataReferences
(
solution
,
"PortableProject"
,
LanguageNames
.
CSharp
,
@"
...
...
@@ -143,10 +184,11 @@ public class DerivedClass : Alias2 { }
Assert
.
Equal
(
derivedClassSymbol
,
derivedDependentType
);
}
[
Fact
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedTypes_CSharp_PortableProfile7
()
[
Theory
,
CombinatorialData
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedTypes_CSharp_PortableProfile7
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create portable assembly with an abstract base class
solution
=
AddProjectWithMetadataReferences
(
solution
,
"PortableProject"
,
LanguageNames
.
CSharp
,
@"
...
...
@@ -183,10 +225,11 @@ public class DerivedClass : BaseClass { }
Assert
.
Equal
(
derivedClassSymbol
,
derivedDependentType
);
}
[
Fact
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedTypes_VisualBasic
()
[
Theory
,
CombinatorialData
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedTypes_VisualBasic
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create portable assembly with an abstract base class
solution
=
AddProjectWithMetadataReferences
(
solution
,
"PortableProject"
,
LanguageNames
.
VisualBasic
,
@"
...
...
@@ -224,10 +267,11 @@ End Namespace
Assert
.
Equal
(
derivedClassSymbol
,
derivedDependentType
);
}
[
Fact
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedTypes_CrossLanguage
()
[
Theory
,
CombinatorialData
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedTypes_CrossLanguage
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create portable assembly with an abstract base class
solution
=
AddProjectWithMetadataReferences
(
solution
,
"PortableProject"
,
LanguageNames
.
CSharp
,
@"
...
...
@@ -265,10 +309,11 @@ End Namespace
Assert
.
Equal
(
derivedClassSymbol
,
derivedDependentType
);
}
[
Fact
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedAndImplementingInterfaces_CSharp
()
[
Theory
,
CombinatorialData
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedAndImplementingInterfaces_CSharp
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create portable assembly with an interface
solution
=
AddProjectWithMetadataReferences
(
solution
,
"PortableProject"
,
LanguageNames
.
CSharp
,
@"
...
...
@@ -304,10 +349,11 @@ public class ImplementingClass : IBaseInterface { }
Assert
.
Equal
(
implementingClassSymbol
,
Assert
.
Single
(
typesThatImplementInterface
));
}
[
Fact
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedInterfaces_VisualBasic
()
[
Theory
,
CombinatorialData
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedInterfaces_VisualBasic
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create portable assembly with an interface
solution
=
AddProjectWithMetadataReferences
(
solution
,
"PortableProject"
,
LanguageNames
.
VisualBasic
,
@"
...
...
@@ -344,10 +390,11 @@ End Namespace
Assert
.
Equal
(
implementingClassSymbol
,
Assert
.
Single
(
typesThatImplementInterface
));
}
[
Fact
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedAndImplementingInterfaces_CrossLanguage
()
[
Theory
,
CombinatorialData
,
WorkItem
(
4973
,
"https://github.com/dotnet/roslyn/issues/4973"
)]
public
async
Task
ImmediatelyDerivedAndImplementingInterfaces_CrossLanguage
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create portable assembly with an interface
solution
=
AddProjectWithMetadataReferences
(
solution
,
"PortableProject"
,
LanguageNames
.
VisualBasic
,
@"
...
...
@@ -383,10 +430,11 @@ public class ImplementingClass : IBaseInterface { }
Assert
.
Equal
(
implementingClassSymbol
,
Assert
.
Single
(
typesThatImplementInterface
));
}
[
Fact
]
public
async
Task
DerivedMetadataClasses
()
[
Theory
,
CombinatorialData
]
public
async
Task
DerivedMetadataClasses
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create a normal assembly with a type derived from the portable abstract base
solution
=
AddProjectWithMetadataReferences
(
solution
,
"NormalProject"
,
LanguageNames
.
CSharp
,
@""
,
MscorlibRef
);
...
...
@@ -413,10 +461,11 @@ public async Task DerivedMetadataClasses()
Assert
.
True
(
transitiveDerived
.
Count
()
>
immediateDerived
.
Count
());
}
[
Fact
]
public
async
Task
DerivedSourceInterfaces
()
[
Theory
,
CombinatorialData
]
public
async
Task
DerivedSourceInterfaces
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create a normal assembly with a type derived from the portable abstract base
solution
=
AddProjectWithMetadataReferences
(
solution
,
"NormalProject"
,
LanguageNames
.
CSharp
,
@"
...
...
@@ -461,10 +510,11 @@ interface IOther { }
Assert
.
True
(
transitiveDerived
.
Count
()
>
immediateDerived
.
Count
());
}
[
Fact
]
public
async
Task
ImplementingSourceTypes
()
[
Theory
,
CombinatorialData
]
public
async
Task
ImplementingSourceTypes
(
TestHost
host
)
{
var
solution
=
new
AdhocWorkspace
().
CurrentSolution
;
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create a normal assembly with a type derived from the portable abstract base
solution
=
AddProjectWithMetadataReferences
(
solution
,
"NormalProject"
,
LanguageNames
.
CSharp
,
@"
...
...
@@ -511,5 +561,62 @@ struct OtherStruct { }
Assert
.
True
(
transitiveImpls
.
Count
()
>
immediateImpls
.
Count
());
}
[
Theory
,
CombinatorialData
]
public
async
Task
ImplementingTypesDoesProduceDelegates
(
TestHost
host
)
{
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create a normal assembly with a type derived from the portable abstract base
solution
=
AddProjectWithMetadataReferences
(
solution
,
"NormalProject"
,
LanguageNames
.
CSharp
,
@"
delegate void D();
"
,
MscorlibRef
);
// get symbols for types
var
compilation
=
await
GetNormalProject
(
solution
).
GetCompilationAsync
();
var
rootType
=
compilation
.
GetTypeByMetadataName
(
"System.ICloneable"
);
Assert
.
NotNull
(
rootType
);
var
transitiveImpls
=
await
SymbolFinder
.
FindImplementationsAsync
(
rootType
,
solution
,
transitive
:
true
);
var
delegates
=
transitiveImpls
.
Where
(
i
=>
i
.
TypeKind
==
TypeKind
.
Delegate
);
Assert
.
NotEmpty
(
delegates
);
// We should find delegates when looking for implementations
Assert
.
True
(
delegates
.
Any
(
i
=>
i
.
Locations
.
Any
(
loc
=>
loc
.
IsInMetadata
)),
"We should find a metadata delegate"
);
Assert
.
Single
(
delegates
.
Where
(
i
=>
i
.
Locations
.
Any
(
loc
=>
loc
.
IsInSource
)));
// We should find a single source delegate
}
[
Theory
,
CombinatorialData
]
public
async
Task
ImplementingTypesDoesProduceEnums
(
TestHost
host
)
{
using
var
workspace
=
GetWorkspace
(
host
);
var
solution
=
workspace
.
CurrentSolution
;
// create a normal assembly with a type derived from the portable abstract base
solution
=
AddProjectWithMetadataReferences
(
solution
,
"NormalProject"
,
LanguageNames
.
CSharp
,
@"
enum E
{
A, B, C,
}
"
,
MscorlibRef
);
// get symbols for types
var
compilation
=
await
GetNormalProject
(
solution
).
GetCompilationAsync
();
var
rootType
=
compilation
.
GetTypeByMetadataName
(
"System.IComparable"
);
Assert
.
NotNull
(
rootType
);
var
transitiveImpls
=
await
SymbolFinder
.
FindImplementationsAsync
(
rootType
,
solution
,
transitive
:
true
);
var
enums
=
transitiveImpls
.
Where
(
i
=>
i
.
TypeKind
==
TypeKind
.
Enum
);
Assert
.
NotEmpty
(
enums
);
// We should find enums when looking for implementations
Assert
.
True
(
enums
.
Any
(
i
=>
i
.
Locations
.
Any
(
loc
=>
loc
.
IsInMetadata
)),
"We should find a metadata enum"
);
Assert
.
Single
(
enums
.
Where
(
i
=>
i
.
Locations
.
Any
(
loc
=>
loc
.
IsInSource
)));
// We should find a single source type
}
}
}
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder.cs
浏览文件 @
da62ba87
...
...
@@ -27,14 +27,21 @@ namespace Microsoft.CodeAnalysis.FindSymbols
using
SymbolSet
=
HashSet
<
INamedTypeSymbol
>;
/// <summary>
/// Provides helper methods for finding dependent types (derivations, implementations,
/// etc.) across a solution. The results found are returned in pairs of <see cref="ISymbol"/>s
/// and <see cref="ProjectId"/>s. The Ids specify what project we were searching in when
/// we found the symbol. That project has the compilation that we found the specific
/// source or metadata symbol within. Note that for metadata symbols there could be
/// many projects where the same symbol could be found. However, we only return the
/// first instance we found.
/// Provides helper methods for finding dependent types (derivations, implementations, etc.) across a solution. This
/// is effectively a graph walk between INamedTypeSymbols walking down the inheritance hierarchy to find related
/// types based either on <see cref="ITypeSymbol.BaseType"/> or <see cref="ITypeSymbol.Interfaces"/>.
/// </summary>
/// <remarks>
/// While walking up the inheritance hierarchy is trivial (as the information is directly contained on the <see
/// cref="ITypeSymbol"/>'s themselves), walking down is complicated. The general way this works is by using
/// out-of-band indices that are built that store this type information in a weak manner. Specifically, for both
/// source and metadata types we have indices that map between the base type name and the inherited type name. i.e.
/// for the case <c>class A { } class B : A { }</c> the index stores a link saying "There is a type 'A' somewhere
/// which has derived type called 'B' somewhere". So when the index is examined for the name 'A', it will say
/// 'examine types called 'B' to see if they're an actual match'.
/// <para/>
/// These links are then continually tranversed to get the full set of results.
/// </remarks>
internal
static
partial
class
DependentTypeFinder
{
// Static helpers so we can pass delegates around without allocations.
...
...
@@ -174,7 +181,7 @@ internal static partial class DependentTypeFinder
// We might miss a derived type in C if there's an intermediate derived type
// in B.
//
// However, say we have projects A <- B <- C <- D, only
only
projects A and C
// However, say we have projects A <- B <- C <- D, only projects A and C
// are passed in. There is no need to check D as there's no way it could
// contribute an intermediate type that affects A or C. We only need to check
// A, B and C
...
...
@@ -187,7 +194,7 @@ internal static partial class DependentTypeFinder
// and the list of projects the caller wants to search, find the actual list of
// projects we need to search through.
//
// This list of projects is properly topologicaly ordered. Because of this we
// This list of projects is properly topological
l
y ordered. Because of this we
// can just process them in order from first to last because we know no project
// in this list could affect a prior project.
var
orderedProjectsToExamine
=
GetOrderedProjectsToExamine
(
...
...
@@ -198,7 +205,7 @@ internal static partial class DependentTypeFinder
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
ht
ese.
// is from metadata). Will be used when examining new types to see if they inherit from any of
th
ese.
using
var
_2
=
GetSymbolSet
(
out
var
currentMetadataTypes
);
// Same as above, but contains source types as well.
...
...
@@ -318,9 +325,7 @@ private static void AddRange(SymbolSet foundTypes, SymbolSet result)
result
.
Add
(
type
);
}
private
static
void
AddRange
(
SymbolSet
foundTypes
,
SymbolSet
currentTypes
,
Func
<
INamedTypeSymbol
,
bool
>
shouldContinueSearching
)
private
static
void
AddRange
(
SymbolSet
foundTypes
,
SymbolSet
currentTypes
,
Func
<
INamedTypeSymbol
,
bool
>
shouldContinueSearching
)
{
// Directly enumerate to avoid IEnumerator allocations.
foreach
(
var
type
in
foundTypes
)
...
...
@@ -448,7 +453,7 @@ private static void AddRange(SymbolSet foundTypes, SymbolSet result)
}
private
static
async
Task
AddDescendantMetadataTypesInProjectAsync
(
SymbolSet
m
etadataTypes
,
SymbolSet
currentM
etadataTypes
,
SymbolSet
result
,
Project
project
,
Func
<
INamedTypeSymbol
,
SymbolSet
,
bool
>
typeMatches
,
...
...
@@ -458,7 +463,7 @@ private static void AddRange(SymbolSet foundTypes, SymbolSet result)
{
Debug
.
Assert
(
project
.
SupportsCompilation
);
if
(
m
etadataTypes
.
Count
==
0
)
if
(
currentM
etadataTypes
.
Count
==
0
)
return
;
var
compilation
=
await
project
.
GetCompilationAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
...
...
@@ -466,7 +471,7 @@ private static void AddRange(SymbolSet foundTypes, SymbolSet result)
using
var
_1
=
GetSymbolSet
(
out
var
typesToSearchFor
);
using
var
_2
=
GetSymbolSet
(
out
var
tempBuffer
);
typesToSearchFor
.
AddAll
(
m
etadataTypes
);
typesToSearchFor
.
AddAll
(
currentM
etadataTypes
);
// As long as there are new types to search for, keep looping.
while
(
typesToSearchFor
.
Count
>
0
)
...
...
@@ -504,7 +509,7 @@ private static void AddRange(SymbolSet foundTypes, SymbolSet result)
// to the names of the all the types that either immediately derive or
// implement that type. Because the mapping is from the simple name
// we might get false positives. But that's fine as we still use
// '
metadataTy
peMatches' to make sure the match is correct.
// '
t
peMatches' to make sure the match is correct.
var
symbolTreeInfo
=
await
SymbolTreeInfo
.
GetInfoForMetadataReferenceAsync
(
project
.
Solution
,
reference
,
loadOnly
:
false
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
...
...
@@ -546,7 +551,7 @@ private static bool TypeHasInterfaceInSet(INamedTypeSymbol type, SymbolSet set)
}
private
static
async
Task
AddDescendantSourceTypesInProjectAsync
(
SymbolSet
s
ourceAndMetadataTypes
,
SymbolSet
currentS
ourceAndMetadataTypes
,
SymbolSet
result
,
Project
project
,
Func
<
INamedTypeSymbol
,
SymbolSet
,
bool
>
typeMatches
,
...
...
@@ -558,14 +563,14 @@ private static bool TypeHasInterfaceInSet(INamedTypeSymbol type, SymbolSet set)
// We're going to be sweeping over this project over and over until we reach a
// fixed point. In order to limit GC and excess work, we cache all the semantic
// models and DeclaredSymbolInfo for
ht
e documents we look at.
// models and DeclaredSymbolInfo for
th
e documents we look at.
// Because we're only processing a project at a time, this is not an issue.
var
cachedModels
=
new
ConcurrentSet
<
SemanticModel
>();
using
var
_1
=
GetSymbolSet
(
out
var
typesToSearchFor
);
using
var
_2
=
GetSymbolSet
(
out
var
tempBuffer
);
typesToSearchFor
.
AddAll
(
s
ourceAndMetadataTypes
);
typesToSearchFor
.
AddAll
(
currentS
ourceAndMetadataTypes
);
var
projectIndex
=
await
ProjectIndex
.
GetIndexAsync
(
project
,
cancellationToken
).
ConfigureAwait
(
false
);
...
...
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder_DerivedClasses.cs
浏览文件 @
da62ba87
...
...
@@ -6,6 +6,7 @@
using
System.Collections.Immutable
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.Internal.Log
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.FindSymbols
...
...
@@ -14,10 +15,27 @@ namespace Microsoft.CodeAnalysis.FindSymbols
internal
static
partial
class
DependentTypeFinder
{
/// <summary>
/// This is an internal implementation of <see cref="SymbolFinder.FindDerivedClassesAsync(INamedTypeSymbol, Solution, IImmutableSet{Project}, CancellationToken)"/>, which is a publically callable method.
/// </summary>
public
static
Task
<
ImmutableArray
<
INamedTypeSymbol
>>
FindAndCacheDerivedClassesAsync
(
public
static
async
Task
<
ImmutableArray
<
INamedTypeSymbol
>>
FindAndCacheDerivedClassesAsync
(
INamedTypeSymbol
type
,
Solution
solution
,
IImmutableSet
<
Project
>
projects
,
bool
transitive
,
CancellationToken
cancellationToken
)
{
var
result
=
await
TryFindAndCacheRemoteTypesAsync
(
type
,
solution
,
projects
,
transitive
,
FunctionId
.
DependentTypeFinder_FindAndCacheDerivedClassesAsync
,
nameof
(
IRemoteDependentTypeFinder
.
FindAndCacheDerivedClassesAsync
),
cancellationToken
).
ConfigureAwait
(
false
);
if
(
result
.
HasValue
)
return
result
.
Value
;
return
await
FindAndCacheDerivedClassesInCurrentProcessAsync
(
type
,
solution
,
projects
,
transitive
,
cancellationToken
).
ConfigureAwait
(
false
);
}
private
static
Task
<
ImmutableArray
<
INamedTypeSymbol
>>
FindAndCacheDerivedClassesInCurrentProcessAsync
(
INamedTypeSymbol
type
,
Solution
solution
,
IImmutableSet
<
Project
>
projects
,
...
...
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder_DerivedInterfaces.cs
浏览文件 @
da62ba87
...
...
@@ -6,6 +6,7 @@
using
System.Collections.Immutable
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.Internal.Log
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.FindSymbols
...
...
@@ -14,7 +15,27 @@ namespace Microsoft.CodeAnalysis.FindSymbols
internal
static
partial
class
DependentTypeFinder
{
public
static
Task
<
ImmutableArray
<
INamedTypeSymbol
>>
FindAndCacheDerivedInterfacesAsync
(
public
static
async
Task
<
ImmutableArray
<
INamedTypeSymbol
>>
FindAndCacheDerivedInterfacesAsync
(
INamedTypeSymbol
type
,
Solution
solution
,
IImmutableSet
<
Project
>
projects
,
bool
transitive
,
CancellationToken
cancellationToken
)
{
var
result
=
await
TryFindAndCacheRemoteTypesAsync
(
type
,
solution
,
projects
,
transitive
,
FunctionId
.
DependentTypeFinder_FindAndCacheDerivedInterfacesAsync
,
nameof
(
IRemoteDependentTypeFinder
.
FindAndCacheDerivedInterfacesAsync
),
cancellationToken
).
ConfigureAwait
(
false
);
if
(
result
.
HasValue
)
return
result
.
Value
;
return
await
FindAndCacheDerivedInterfacesInCurrentProcessAsync
(
type
,
solution
,
projects
,
transitive
,
cancellationToken
).
ConfigureAwait
(
false
);
}
private
static
Task
<
ImmutableArray
<
INamedTypeSymbol
>>
FindAndCacheDerivedInterfacesInCurrentProcessAsync
(
INamedTypeSymbol
type
,
Solution
solution
,
IImmutableSet
<
Project
>
projects
,
...
...
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder_ImplementingTypes.cs
浏览文件 @
da62ba87
...
...
@@ -6,6 +6,7 @@
using
System.Collections.Immutable
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.Internal.Log
;
namespace
Microsoft.CodeAnalysis.FindSymbols
{
...
...
@@ -13,11 +14,27 @@ namespace Microsoft.CodeAnalysis.FindSymbols
internal
static
partial
class
DependentTypeFinder
{
/// <summary>
/// Implementation of <see cref="SymbolFinder.FindImplementationsAsync(ISymbol, Solution, IImmutableSet{Project}, CancellationToken)"/> for
/// <see cref="INamedTypeSymbol"/>s
/// </summary>
public
static
Task
<
ImmutableArray
<
INamedTypeSymbol
>>
FindAndCacheImplementingTypesAsync
(
public
static
async
Task
<
ImmutableArray
<
INamedTypeSymbol
>>
FindAndCacheImplementingTypesAsync
(
INamedTypeSymbol
type
,
Solution
solution
,
IImmutableSet
<
Project
>
projects
,
bool
transitive
,
CancellationToken
cancellationToken
)
{
var
result
=
await
TryFindAndCacheRemoteTypesAsync
(
type
,
solution
,
projects
,
transitive
,
FunctionId
.
DependentTypeFinder_FindAndCacheImplementingTypesAsync
,
nameof
(
IRemoteDependentTypeFinder
.
FindAndCacheImplementingTypesAsync
),
cancellationToken
).
ConfigureAwait
(
false
);
if
(
result
.
HasValue
)
return
result
.
Value
;
return
await
FindAndCacheImplementingTypesInCurrentProcessAsync
(
type
,
solution
,
projects
,
transitive
,
cancellationToken
).
ConfigureAwait
(
false
);
}
private
static
Task
<
ImmutableArray
<
INamedTypeSymbol
>>
FindAndCacheImplementingTypesInCurrentProcessAsync
(
INamedTypeSymbol
type
,
Solution
solution
,
IImmutableSet
<
Project
>
projects
,
...
...
@@ -67,9 +84,14 @@ static bool TypeMatches(INamedTypeSymbol type, SymbolSet set)
transitive
:
transitive
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
// Only classes/struct implement interface types. Derived interfaces can be found with
// FindDerivedInterfacesAsync.
return
allTypes
.
WhereAsArray
(
t
=>
t
.
TypeKind
==
TypeKind
.
Class
||
t
.
TypeKind
==
TypeKind
.
Struct
);
// Only classes/struct/delegates/enums implement interface types. Derived interfaces can be found with
// FindDerivedInterfacesAsync. Delegates/Enums only happen in a few corner cases. For example, enums
// implement IComparable, and delegates implement ICloneable.
return
allTypes
.
WhereAsArray
(
t
=>
t
.
TypeKind
==
TypeKind
.
Class
||
t
.
TypeKind
==
TypeKind
.
Struct
||
t
.
TypeKind
==
TypeKind
.
Delegate
||
t
.
TypeKind
==
TypeKind
.
Enum
);
}
return
ImmutableArray
<
INamedTypeSymbol
>.
Empty
;
...
...
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder_Remote.cs
0 → 100644
浏览文件 @
da62ba87
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using
System.Collections.Immutable
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.Internal.Log
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Remote
;
namespace
Microsoft.CodeAnalysis.FindSymbols
{
internal
static
partial
class
DependentTypeFinder
{
public
static
async
Task
<
ImmutableArray
<
INamedTypeSymbol
>?>
TryFindAndCacheRemoteTypesAsync
(
INamedTypeSymbol
type
,
Solution
solution
,
IImmutableSet
<
Project
>
projects
,
bool
transitive
,
FunctionId
functionId
,
string
remoteFunctionName
,
CancellationToken
cancellationToken
)
{
using
(
Logger
.
LogBlock
(
functionId
,
cancellationToken
))
{
var
client
=
await
RemoteHostClient
.
TryGetClientAsync
(
solution
.
Workspace
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
client
!=
null
)
{
var
result
=
await
client
.
TryRunRemoteAsync
<
ImmutableArray
<
SerializableSymbolAndProjectId
>>(
WellKnownServiceHubServices
.
CodeAnalysisService
,
remoteFunctionName
,
solution
,
new
object
[]
{
SerializableSymbolAndProjectId
.
Dehydrate
(
solution
,
type
,
cancellationToken
),
projects
?.
Select
(
p
=>
p
.
Id
).
ToArray
(),
transitive
,
},
null
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
result
.
HasValue
)
{
return
await
RehydrateAsync
(
solution
,
result
.
Value
,
cancellationToken
).
ConfigureAwait
(
false
);
}
}
}
return
null
;
}
private
static
async
Task
<
ImmutableArray
<
INamedTypeSymbol
>>
RehydrateAsync
(
Solution
solution
,
ImmutableArray
<
SerializableSymbolAndProjectId
>
values
,
CancellationToken
cancellationToken
)
{
using
var
_
=
ArrayBuilder
<
INamedTypeSymbol
>.
GetInstance
(
out
var
builder
);
foreach
(
var
item
in
values
)
{
var
rehydrated
=
await
item
.
TryRehydrateAsync
(
solution
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
rehydrated
is
INamedTypeSymbol
namedType
)
builder
.
AddIfNotNull
(
namedType
);
}
return
builder
.
ToImmutable
();
}
}
}
src/Workspaces/Core/Portable/FindSymbols/FindReferences/IRemoteDependentTypeFinder.cs
0 → 100644
浏览文件 @
da62ba87
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using
System.Collections.Immutable
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.Remote
;
namespace
Microsoft.CodeAnalysis.FindSymbols
{
internal
interface
IRemoteDependentTypeFinder
{
Task
<
ImmutableArray
<
SerializableSymbolAndProjectId
>>
FindAndCacheDerivedClassesAsync
(
PinnedSolutionInfo
solutionInfo
,
SerializableSymbolAndProjectId
type
,
ProjectId
[]
projects
,
bool
transitive
,
CancellationToken
cancellationToken
);
Task
<
ImmutableArray
<
SerializableSymbolAndProjectId
>>
FindAndCacheDerivedInterfacesAsync
(
PinnedSolutionInfo
solutionInfo
,
SerializableSymbolAndProjectId
type
,
ProjectId
[]
projects
,
bool
transitive
,
CancellationToken
cancellationToken
);
Task
<
ImmutableArray
<
SerializableSymbolAndProjectId
>>
FindAndCacheImplementingTypesAsync
(
PinnedSolutionInfo
solutionInfo
,
SerializableSymbolAndProjectId
type
,
ProjectId
[]
projects
,
bool
transitive
,
CancellationToken
cancellationToken
);
}
}
src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_DependentTypeFinder.cs
0 → 100644
浏览文件 @
da62ba87
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using
System
;
using
System.Collections.Immutable
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.FindSymbols
;
namespace
Microsoft.CodeAnalysis.Remote
{
// root level service for all Roslyn services
internal
partial
class
CodeAnalysisService
:
IRemoteDependentTypeFinder
{
private
Task
<
ImmutableArray
<
SerializableSymbolAndProjectId
>>
FindAndCacheTypesAsync
(
PinnedSolutionInfo
solutionInfo
,
SerializableSymbolAndProjectId
typeAndProjectId
,
ProjectId
[]
projectIds
,
Func
<
INamedTypeSymbol
,
Solution
,
ImmutableHashSet
<
Project
>,
Task
<
ImmutableArray
<
INamedTypeSymbol
>>>
func
,
CancellationToken
cancellationToken
)
{
return
RunServiceAsync
(
async
()
=>
{
using
(
UserOperationBooster
.
Boost
())
{
var
solution
=
await
GetSolutionAsync
(
solutionInfo
,
cancellationToken
).
ConfigureAwait
(
false
);
var
symbol
=
await
typeAndProjectId
.
TryRehydrateAsync
(
solution
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(!(
symbol
is
INamedTypeSymbol
namedType
))
return
ImmutableArray
<
SerializableSymbolAndProjectId
>.
Empty
;
var
projects
=
projectIds
?.
Select
(
id
=>
solution
.
GetProject
(
id
)).
ToImmutableHashSet
();
var
types
=
await
func
(
namedType
,
solution
,
projects
).
ConfigureAwait
(
false
);
return
types
.
SelectAsArray
(
(
Func
<
INamedTypeSymbol
,
SerializableSymbolAndProjectId
>)(
t
=>
SerializableSymbolAndProjectId
.
Dehydrate
(
solution
,
t
,
cancellationToken
)));
}
},
cancellationToken
);
}
public
Task
<
ImmutableArray
<
SerializableSymbolAndProjectId
>>
FindAndCacheDerivedClassesAsync
(
PinnedSolutionInfo
solutionInfo
,
SerializableSymbolAndProjectId
typeAndProjectId
,
ProjectId
[]
projectIds
,
bool
transitive
,
CancellationToken
cancellationToken
)
{
return
FindAndCacheTypesAsync
(
solutionInfo
,
typeAndProjectId
,
projectIds
,
(
nt
,
s
,
ps
)
=>
DependentTypeFinder
.
FindAndCacheDerivedClassesAsync
(
nt
,
s
,
ps
,
transitive
,
cancellationToken
),
cancellationToken
);
}
public
Task
<
ImmutableArray
<
SerializableSymbolAndProjectId
>>
FindAndCacheDerivedInterfacesAsync
(
PinnedSolutionInfo
solutionInfo
,
SerializableSymbolAndProjectId
typeAndProjectId
,
ProjectId
[]
projectIds
,
bool
transitive
,
CancellationToken
cancellationToken
)
{
return
FindAndCacheTypesAsync
(
solutionInfo
,
typeAndProjectId
,
projectIds
,
(
nt
,
s
,
ps
)
=>
DependentTypeFinder
.
FindAndCacheDerivedInterfacesAsync
(
nt
,
s
,
ps
,
transitive
,
cancellationToken
),
cancellationToken
);
}
public
Task
<
ImmutableArray
<
SerializableSymbolAndProjectId
>>
FindAndCacheImplementingTypesAsync
(
PinnedSolutionInfo
solutionInfo
,
SerializableSymbolAndProjectId
typeAndProjectId
,
ProjectId
[]
projectIds
,
bool
transitive
,
CancellationToken
cancellationToken
)
{
return
FindAndCacheTypesAsync
(
solutionInfo
,
typeAndProjectId
,
projectIds
,
(
nt
,
s
,
ps
)
=>
DependentTypeFinder
.
FindAndCacheImplementingTypesAsync
(
nt
,
s
,
ps
,
transitive
,
cancellationToken
),
cancellationToken
);
}
}
}
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs
浏览文件 @
da62ba87
...
...
@@ -484,10 +484,14 @@ internal enum FunctionId
Renamer_FindRenameLocationsAsync
=
387
,
Renamer_ResolveConflictsAsync
=
388
,
ChangeSignature_Data
=
389
,
ChangeSignature_Data
=
400
,
AbstractEncapsulateFieldService_EncapsulateFieldsAsync
=
39
0
,
AbstractEncapsulateFieldService_EncapsulateFieldsAsync
=
41
0
,
AbstractConvertTupleToStructCodeRefactoringProvider_ConvertToStructAsync
=
400
,
AbstractConvertTupleToStructCodeRefactoringProvider_ConvertToStructAsync
=
420
,
DependentTypeFinder_FindAndCacheDerivedClassesAsync
=
430
,
DependentTypeFinder_FindAndCacheDerivedInterfacesAsync
=
431
,
DependentTypeFinder_FindAndCacheImplementingTypesAsync
=
432
,
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录