Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
d408866d
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,发现更多精彩内容 >>
提交
d408866d
编写于
4月 18, 2020
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix goto-impl multi-targetting
上级
24911dad
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
74 addition
and
59 deletion
+74
-59
src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
...itorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
+13
-10
src/EditorFeatures/Core/FindUsages/FindUsagesHelpers.cs
src/EditorFeatures/Core/FindUsages/FindUsagesHelpers.cs
+45
-38
src/EditorFeatures/Core/GoToBase/AbstractGoToBaseService.cs
src/EditorFeatures/Core/GoToBase/AbstractGoToBaseService.cs
+13
-9
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder.cs
...ortable/FindSymbols/FindReferences/DependentTypeFinder.cs
+2
-2
src/Workspaces/Core/Portable/FindSymbols/SymbolFinder.cs
src/Workspaces/Core/Portable/FindSymbols/SymbolFinder.cs
+1
-0
未找到文件。
src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
浏览文件 @
d408866d
...
...
@@ -29,17 +29,16 @@ protected AbstractFindUsagesService(IThreadingContext threadingContext)
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
var
cancellationToken
=
context
.
CancellationToken
;
var
tuple
=
await
FindUsagesHelpers
.
Find
ImplementationsAsync
(
var
tuple
Opt
=
await
FindUsagesHelpers
.
FindSource
ImplementationsAsync
(
document
,
position
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
tuple
==
null
)
if
(
tuple
Opt
==
null
)
{
await
context
.
ReportMessageAsync
(
EditorFeaturesResources
.
Cannot_navigate_to_the_symbol_under_the_caret
).
ConfigureAwait
(
false
);
return
;
}
var
message
=
tuple
.
Value
.
message
;
var
(
symbolAndProjectId
,
implementations
,
message
)
=
tupleOpt
.
Value
;
if
(
message
!=
null
)
{
await
context
.
ReportMessageAsync
(
message
).
ConfigureAwait
(
false
);
...
...
@@ -48,13 +47,13 @@ protected AbstractFindUsagesService(IThreadingContext threadingContext)
await
context
.
SetSearchTitleAsync
(
string
.
Format
(
EditorFeaturesResources
.
_0_implementations
,
FindUsagesHelpers
.
GetDisplayName
(
tuple
.
Value
.
s
ymbol
))).
ConfigureAwait
(
false
);
FindUsagesHelpers
.
GetDisplayName
(
symbolAndProjectId
.
S
ymbol
))).
ConfigureAwait
(
false
);
var
project
=
tuple
.
Value
.
project
;
foreach
(
var
implementation
in
tuple
.
Value
.
implementations
)
var
solution
=
document
.
Project
.
Solution
;
foreach
(
var
implementation
in
implementations
)
{
var
definitionItem
=
await
implementation
.
ToClassifiedDefinitionItemAsync
(
project
,
includeHiddenLocations
:
false
,
var
definitionItem
=
await
implementation
.
Symbol
.
ToClassifiedDefinitionItemAsync
(
solution
.
GetProject
(
implementation
.
ProjectId
)
,
includeHiddenLocations
:
false
,
FindReferencesSearchOptions
.
Default
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
await
context
.
OnDefinitionFoundAsync
(
definitionItem
).
ConfigureAwait
(
false
);
}
...
...
@@ -128,8 +127,12 @@ protected AbstractFindUsagesService(IThreadingContext threadingContext)
if
(
symbolAndProject
==
null
)
return
;
var
solution
=
document
.
Project
.
Solution
;
await
FindSymbolReferencesAsync
(
_threadingContext
,
context
,
symbolAndProject
.
Value
.
symbol
,
symbolAndProject
.
Value
.
project
,
cancellationToken
).
ConfigureAwait
(
false
);
_threadingContext
,
context
,
symbolAndProject
.
Value
.
Symbol
,
solution
.
GetRequiredProject
(
symbolAndProject
.
Value
.
ProjectId
),
cancellationToken
).
ConfigureAwait
(
false
);
}
/// <summary>
...
...
src/EditorFeatures/Core/FindUsages/FindUsagesHelpers.cs
浏览文件 @
d408866d
...
...
@@ -9,6 +9,7 @@
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Shared.Utilities
;
using
Microsoft.CodeAnalysis.SymbolMapping
;
using
Roslyn.Utilities
;
...
...
@@ -29,16 +30,14 @@ public static string GetDisplayName(ISymbol symbol)
/// there may be symbol mapping involved (for example in Metadata-As-Source
/// scenarios).
/// </summary>
public
static
async
Task
<
(
ISymbol
symbol
,
Project
project
)
?>
GetRelevantSymbolAndProjectAtPositionAsync
(
public
static
async
Task
<
SymbolAndProjectId
?>
GetRelevantSymbolAndProjectAtPositionAsync
(
Document
document
,
int
position
,
CancellationToken
cancellationToken
)
{
cancellationToken
.
ThrowIfCancellationRequested
();
var
symbol
=
await
SymbolFinder
.
FindSymbolAtPositionAsync
(
document
,
position
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
if
(
symbol
==
null
)
{
return
null
;
}
// If this document is not in the primary workspace, we may want to search for results
// in a solution different from the one we started in. Use the starting workspace's
...
...
@@ -47,53 +46,58 @@ public static string GetDisplayName(ISymbol symbol)
var
mapping
=
await
mappingService
.
MapSymbolAsync
(
document
,
symbol
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
mapping
==
null
)
{
return
null
;
}
return
(
mapping
.
Symbol
,
mapping
.
Project
);
return
new
SymbolAndProjectId
(
mapping
.
Symbol
,
mapping
.
Project
.
Id
);
}
public
static
async
Task
<(
ISymbol
symbol
,
Project
project
,
ImmutableArray
<
ISymbol
>
implementations
,
string
message
)?>
Find
ImplementationsAsync
(
Document
document
,
int
position
,
CancellationToken
cancellationToken
)
public
static
async
Task
<(
SymbolAndProjectId
symboAndProjectId
,
ImmutableArray
<
SymbolAndProjectId
>
implementations
,
string
message
)?>
FindSource
ImplementationsAsync
(
Document
document
,
int
position
,
CancellationToken
cancellationToken
)
{
var
symbolAndProject
=
await
GetRelevantSymbolAndProjectAtPositionAsync
(
document
,
position
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
symbolAndProject
==
null
)
{
return
null
;
}
return
await
FindImplementationsAsync
(
symbolAndProject
?.
symbol
,
symbolAndProject
?.
project
,
cancellationToken
).
ConfigureAwait
(
false
);
return
await
Find
Source
ImplementationsAsync
(
symbolAndProject
.
Value
,
document
.
Project
.
Solution
,
cancellationToken
).
ConfigureAwait
(
false
);
}
private
static
async
Task
<(
ISymbol
symbol
,
Project
project
,
ImmutableArray
<
ISymbol
>
implementations
,
string
message
)?>
Find
ImplementationsAsync
(
ISymbol
symbol
,
Project
project
,
CancellationToken
cancellationToken
)
private
static
async
Task
<(
SymbolAndProjectId
symbolAndProjectId
,
ImmutableArray
<
SymbolAndProjectId
>
implementations
,
string
message
)?>
FindSource
ImplementationsAsync
(
SymbolAndProjectId
symbolAndProjectId
,
Solution
solution
,
CancellationToken
cancellationToken
)
{
var
implementations
=
await
FindImplementationsWorker
Async
(
symbol
,
project
,
cancellationToken
).
ConfigureAwait
(
false
);
var
linkedSymbols
=
await
SymbolFinder
.
FindLinkedSymbols
Async
(
symbol
AndProjectId
.
Symbol
,
solution
,
cancellationToken
).
ConfigureAwait
(
false
);
var
filteredSymbols
=
implementations
.
WhereAsArray
(
s
=>
s
.
Locations
.
Any
(
l
=>
l
.
IsInSource
));
// If we're in a linked file, try to find all the symbols this links to, and find all the implementations of
// each of those linked symbols. De-dupe the results so the user only gets unique results.
var
builder
=
new
HashSet
<
SymbolAndProjectId
>(
SymbolAndProjectIdComparer
.
SymbolEquivalenceInstance
);
foreach
(
var
linkedSymbol
in
linkedSymbols
)
{
var
implementations
=
await
FindImplementationsWorkerAsync
(
linkedSymbol
,
solution
,
cancellationToken
).
ConfigureAwait
(
false
);
builder
.
AddRange
(
implementations
.
Where
(
s
=>
s
.
Symbol
.
Locations
.
Any
(
l
=>
l
.
IsInSource
)));
}
return
filteredSymbols
.
Length
==
0
?
(
symbol
,
project
,
filteredSymbols
,
EditorFeaturesResources
.
The_symbol_has_no_implementations
)
:
(
symbol
,
project
,
filteredSymbols
,
null
);
var
result
=
builder
.
ToImmutableArray
();
return
result
.
Length
==
0
?
(
symbolAndProjectId
,
result
,
EditorFeaturesResources
.
The_symbol_has_no_implementations
)
:
(
symbolAndProjectId
,
result
,
null
);
}
private
static
async
Task
<
ImmutableArray
<
ISymbol
>>
FindImplementationsWorkerAsync
(
ISymbol
symbol
,
Project
project
,
CancellationToken
cancellationToken
)
private
static
async
Task
<
ImmutableArray
<
SymbolAndProjectId
>>
FindImplementationsWorkerAsync
(
SymbolAndProjectId
symbolAndProjectId
,
Solution
solution
,
CancellationToken
cancellationToken
)
{
var
solution
=
project
.
Solution
;
if
(
symbol
.
IsInterfaceType
()
||
symbol
.
IsImplementableMember
())
if
(
symbolAndProjectId
.
Symbol
.
IsInterfaceType
()
||
symbolAndProjectId
.
Symbol
.
IsImplementableMember
())
{
var
implementations
=
await
SymbolFinder
.
FindImplementationsAsync
(
symbol
,
solution
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
symbol
AndProjectId
,
solution
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
// It's important we use a HashSet here -- we may have cases in an inheritance hierarchy where more than one method
// in an overrides chain implements the same interface method, and we want to duplicate those. The easiest way to do it
// is to just use a HashSet.
var
implementationsAndOverrides
=
new
HashSet
<
ISymbol
>();
var
implementationsAndOverrides
=
new
HashSet
<
SymbolAndProjectId
>();
foreach
(
var
implementation
in
implementations
)
{
...
...
@@ -101,7 +105,7 @@ public static async Task<(ISymbol symbol, Project project, ImmutableArray<ISymbo
// FindImplementationsAsync will only return the base virtual/abstract method, not that method and the overrides
// of the method. We should also include those.
if
(
implementation
.
IsOverridable
())
if
(
implementation
.
Symbol
.
IsOverridable
())
{
var
overrides
=
await
SymbolFinder
.
FindOverridesAsync
(
implementation
,
solution
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
...
...
@@ -109,33 +113,36 @@ public static async Task<(ISymbol symbol, Project project, ImmutableArray<ISymbo
}
}
if
(!
symbol
.
IsInterfaceType
()
&&
!
symbol
.
IsAbstract
)
if
(!
symbolAndProjectId
.
Symbol
.
IsInterfaceType
()
&&
!
symbolAndProjectId
.
Symbol
.
IsAbstract
)
{
implementationsAndOverrides
.
Add
(
symbol
);
implementationsAndOverrides
.
Add
(
symbol
AndProjectId
);
}
return
implementationsAndOverrides
.
ToImmutableArray
();
}
else
if
((
symbol
as
INamedTypeSymbol
)?.
TypeKind
==
TypeKind
.
Class
)
else
if
((
symbol
AndProjectId
.
Symbol
as
INamedTypeSymbol
)?.
TypeKind
==
TypeKind
.
Class
)
{
var
derivedClasses
=
await
SymbolFinder
.
FindDerivedClassesAsync
(
(
INamedTypeSymbol
)
symbol
,
solution
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
var
implementations
=
derivedClasses
.
Concat
(
symbol
);
symbolAndProjectId
.
WithSymbol
((
INamedTypeSymbol
)
symbolAndProjectId
.
Symbol
),
solution
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
var
implementations
=
derivedClasses
.
SelectAsArray
(
s
=>
(
SymbolAndProjectId
)
s
).
Concat
(
symbolAndProjectId
);
return
implementations
.
ToImmutableArray
()
;
return
implementations
;
}
else
if
(
symbol
.
IsOverridable
())
else
if
(
symbol
AndProjectId
.
Symbol
.
IsOverridable
())
{
var
overrides
=
await
SymbolFinder
.
FindOverridesAsync
(
symbol
,
solution
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
var
implementations
=
overrides
.
Concat
(
symbol
);
symbol
AndProjectId
,
solution
,
cancellationToken
:
cancellationToken
).
ConfigureAwait
(
false
);
var
implementations
=
overrides
.
Concat
(
symbol
AndProjectId
);
return
implementations
.
ToImmutableArray
()
;
return
implementations
;
}
else
{
// This is something boring like a regular method or type, so we'll just go there directly
return
ImmutableArray
.
Create
(
symbol
);
return
ImmutableArray
.
Create
(
symbol
AndProjectId
);
}
}
...
...
src/EditorFeatures/Core/GoToBase/AbstractGoToBaseService.cs
浏览文件 @
d408866d
...
...
@@ -7,6 +7,7 @@
using
Microsoft.CodeAnalysis.Editor.FindUsages
;
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.FindUsages
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
namespace
Microsoft.CodeAnalysis.Editor.GoToBase
{
...
...
@@ -15,26 +16,29 @@ internal abstract partial class AbstractGoToBaseService : IGoToBaseService
public
async
Task
FindBasesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
var
cancellationToken
=
context
.
CancellationToken
;
var
symbolAndProject
=
await
FindUsagesHelpers
.
GetRelevantSymbolAndProjectAtPositionAsync
(
var
symbolAndProject
IdOpt
=
await
FindUsagesHelpers
.
GetRelevantSymbolAndProjectAtPositionAsync
(
document
,
position
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
symbolAndProject
==
null
)
if
(
symbolAndProject
IdOpt
==
null
)
{
await
context
.
ReportMessageAsync
(
EditorFeaturesResources
.
Cannot_navigate_to_the_symbol_under_the_caret
).
ConfigureAwait
(
false
);
return
;
}
var
symbol
=
symbolAndProject
.
Value
.
symbol
;
var
solution
=
document
.
Project
.
Solution
;
var
symbolAndProjectId
=
symbolAndProjectIdOpt
.
Value
;
var
symbol
=
symbolAndProjectId
.
Symbol
;
var
bases
=
FindBaseHelpers
.
FindBases
(
symbol
,
symbolAndProject
.
Value
.
project
,
cancellationToken
);
symbolAndProjectId
.
Symbol
,
solution
.
GetRequiredProject
(
symbolAndProjectId
.
ProjectId
),
cancellationToken
);
await
context
.
SetSearchTitleAsync
(
string
.
Format
(
EditorFeaturesResources
.
_0_bases
,
FindUsagesHelpers
.
GetDisplayName
(
symbol
))).
ConfigureAwait
(
false
);
var
project
=
document
.
Project
;
var
solution
=
project
.
Solution
;
var
projectId
=
project
.
Id
;
var
found
=
false
;
...
...
@@ -45,11 +49,11 @@ public async Task FindBasesAsync(Document document, int position, IFindUsagesCon
foreach
(
var
baseSymbol
in
bases
)
{
var
sourceDefinition
=
await
SymbolFinder
.
FindSourceDefinitionAsync
(
SymbolAndProjectId
.
Create
(
baseSymbol
,
projectId
)
,
solution
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
sourceDefinition
.
Symbol
!=
null
)
baseSymbol
,
solution
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
sourceDefinition
!=
null
)
{
var
definitionItem
=
await
sourceDefinition
.
Symbol
.
ToClassifiedDefinitionItemAsync
(
solution
.
GetProject
(
sourceDefinition
.
ProjectId
)
,
includeHiddenLocations
:
false
,
var
definitionItem
=
await
sourceDefinition
.
ToClassifiedDefinitionItemAsync
(
project
,
includeHiddenLocations
:
false
,
FindReferencesSearchOptions
.
Default
,
cancellationToken
:
cancellationToken
)
.
ConfigureAwait
(
false
);
await
context
.
OnDefinitionFoundAsync
(
definitionItem
).
ConfigureAwait
(
false
);
...
...
src/Workspaces/Core/Portable/FindSymbols/FindReferences/DependentTypeFinder.cs
浏览文件 @
d408866d
...
...
@@ -16,7 +16,7 @@
namespace
Microsoft.CodeAnalysis.FindSymbols
{
using
RelatedTypeCache
=
ConditionalWeakTable
<
Solution
,
ConcurrentDictionary
<(
SymbolKey
,
IImmutableSet
<
Project
>),
AsyncLazy
<
ImmutableArray
<(
SymbolKey
,
ProjectId
)>>>>;
using
RelatedTypeCache
=
ConditionalWeakTable
<
Solution
,
ConcurrentDictionary
<(
SymbolKey
,
ProjectId
,
IImmutableSet
<
Project
>),
AsyncLazy
<
ImmutableArray
<(
SymbolKey
,
ProjectId
)>>>>;
using
SymbolAndProjectIdSet
=
HashSet
<
SymbolAndProjectId
<
INamedTypeSymbol
>>;
/// <summary>
...
...
@@ -69,7 +69,7 @@ internal static partial class DependentTypeFinder
// Do a quick lookup first to avoid the allocation. If it fails, go through the
// slower allocating path.
var
key
=
(
type
.
Symbol
.
GetSymbolKey
(),
projects
);
var
key
=
(
type
.
Symbol
.
GetSymbolKey
(),
type
.
ProjectId
,
projects
);
if
(!
dictionary
.
TryGetValue
(
key
,
out
var
lazy
))
{
lazy
=
dictionary
.
GetOrAdd
(
key
,
...
...
src/Workspaces/Core/Portable/FindSymbols/SymbolFinder.cs
浏览文件 @
d408866d
...
...
@@ -252,6 +252,7 @@ public static IEnumerable<TSymbol> FindSimilarSymbols<TSymbol>(TSymbol symbol, C
foreach
(
var
location
in
symbol
.
DeclaringSyntaxReferences
)
{
var
originalDocument
=
solution
.
GetDocument
(
location
.
SyntaxTree
);
linkedSymbols
.
Add
(
new
SymbolAndProjectId
(
symbol
,
originalDocument
.
Project
.
Id
));
// GetDocument will return null for locations in #load'ed trees. TODO: Remove this check and add logic
// to fetch the #load'ed tree's Document once https://github.com/dotnet/roslyn/issues/5260 is fixed.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录