Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
05f93e23
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,发现更多精彩内容 >>
提交
05f93e23
编写于
5月 02, 2020
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Extract code into its own file.
上级
a57a76dd
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
248 addition
and
225 deletion
+248
-225
src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
...itorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
+0
-225
src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService_FindReferences.cs
...re/FindUsages/AbstractFindUsagesService_FindReferences.cs
+248
-0
未找到文件。
src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
浏览文件 @
05f93e23
...
...
@@ -103,230 +103,5 @@ public async Task FindImplementationsAsync(Document document, int position, IFin
await
context
.
OnDefinitionFoundAsync
(
definitionItem
).
ConfigureAwait
(
false
);
}
}
public
async
Task
FindReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
var
definitionTrackingContext
=
new
DefinitionTrackingContext
(
context
);
// Need ConfigureAwait(true) here so we get back to the UI thread before calling
// GetThirdPartyDefinitions. We need to call that on the UI thread to match behavior
// of how the language service always worked in the past.
//
// Any async calls before GetThirdPartyDefinitions must be ConfigureAwait(true).
await
FindLiteralOrSymbolReferencesAsync
(
document
,
position
,
definitionTrackingContext
).
ConfigureAwait
(
true
);
// After the FAR engine is done call into any third party extensions to see
// if they want to add results.
var
thirdPartyDefinitions
=
GetThirdPartyDefinitions
(
document
.
Project
.
Solution
,
definitionTrackingContext
.
GetDefinitions
(),
context
.
CancellationToken
);
// From this point on we can do ConfigureAwait(false) as we're not calling back
// into third parties anymore.
foreach
(
var
definition
in
thirdPartyDefinitions
)
{
// Don't need ConfigureAwait(true) here
await
context
.
OnDefinitionFoundAsync
(
definition
).
ConfigureAwait
(
false
);
}
}
private
async
Task
FindLiteralOrSymbolReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
// First, see if we're on a literal. If so search for literals in the solution with
// the same value.
var
found
=
await
TryFindLiteralReferencesAsync
(
document
,
position
,
context
).
ConfigureAwait
(
false
);
if
(
found
)
{
return
;
}
// Wasn't a literal. Try again as a symbol.
await
FindSymbolReferencesAsync
(
document
,
position
,
context
).
ConfigureAwait
(
false
);
}
private
ImmutableArray
<
DefinitionItem
>
GetThirdPartyDefinitions
(
Solution
solution
,
ImmutableArray
<
DefinitionItem
>
definitions
,
CancellationToken
cancellationToken
)
{
var
factory
=
solution
.
Workspace
.
Services
.
GetRequiredService
<
IDefinitionsAndReferencesFactory
>();
return
definitions
.
Select
(
d
=>
factory
.
GetThirdPartyDefinitionItem
(
solution
,
d
,
cancellationToken
))
.
WhereNotNull
()
.
ToImmutableArray
();
}
private
async
Task
FindSymbolReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
var
cancellationToken
=
context
.
CancellationToken
;
cancellationToken
.
ThrowIfCancellationRequested
();
// Find the symbol we want to search and the solution we want to search in.
var
symbolAndProjectOpt
=
await
FindUsagesHelpers
.
GetRelevantSymbolAndProjectAtPositionAsync
(
document
,
position
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
symbolAndProjectOpt
==
null
)
return
;
var
(
symbol
,
project
)
=
symbolAndProjectOpt
.
Value
;
await
FindSymbolReferencesAsync
(
context
,
symbol
,
project
).
ConfigureAwait
(
false
);
}
/// <summary>
/// Public helper that we use from features like ObjectBrowser which start with a symbol
/// and want to push all the references to it into the Streaming-Find-References window.
/// </summary>
public
static
async
Task
FindSymbolReferencesAsync
(
IFindUsagesContext
context
,
ISymbol
symbol
,
Project
project
)
{
var
solution
=
project
.
Solution
;
var
monikerUsagesService
=
solution
.
Workspace
.
Services
.
GetRequiredService
<
IFindSymbolMonikerUsagesService
>();
await
context
.
SetSearchTitleAsync
(
string
.
Format
(
EditorFeaturesResources
.
_0_references
,
FindUsagesHelpers
.
GetDisplayName
(
symbol
))).
ConfigureAwait
(
false
);
var
options
=
FindReferencesSearchOptions
.
GetFeatureOptionsForStartingSymbol
(
symbol
);
// Now call into the underlying FAR engine to find reference. The FAR
// engine will push results into the 'progress' instance passed into it.
// We'll take those results, massage them, and forward them along to the
// FindReferencesContext instance we were given.
var
normalFindReferencesTask
=
FindReferencesAsync
(
context
,
symbol
,
project
,
options
);
// Kick off work to search the online code index system in parallel
var
codeIndexReferencesTask
=
FindSymbolMonikerReferencesAsync
(
monikerUsagesService
,
symbol
,
context
);
await
Task
.
WhenAll
(
normalFindReferencesTask
,
codeIndexReferencesTask
).
ConfigureAwait
(
false
);
}
public
static
async
Task
FindReferencesAsync
(
IFindUsagesContext
context
,
ISymbol
symbol
,
Project
project
,
FindReferencesSearchOptions
options
)
{
var
cancellationToken
=
context
.
CancellationToken
;
var
solution
=
project
.
Solution
;
var
client
=
await
RemoteHostClient
.
TryGetClientAsync
(
solution
.
Workspace
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
client
!=
null
)
{
// Create a callback that we can pass to the server process to hear about the
// results as it finds them. When we hear about results we'll forward them to
// the 'progress' parameter which will then update the UI.
var
serverCallback
=
new
FindUsagesServerCallback
(
solution
,
context
);
var
success
=
await
client
.
TryRunRemoteAsync
(
WellKnownServiceHubServices
.
CodeAnalysisService
,
nameof
(
IRemoteFindUsagesService
.
FindReferencesAsync
),
solution
,
new
object
[]
{
SerializableSymbolAndProjectId
.
Create
(
symbol
,
project
,
cancellationToken
),
SerializableFindReferencesSearchOptions
.
Dehydrate
(
options
),
},
serverCallback
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
success
)
return
;
}
// Couldn't effectively search in OOP. Perform the search in-process.
await
FindReferencesInCurrentProcessAsync
(
context
,
symbol
,
project
,
options
).
ConfigureAwait
(
false
);
}
private
static
Task
FindReferencesInCurrentProcessAsync
(
IFindUsagesContext
context
,
ISymbol
symbol
,
Project
project
,
FindReferencesSearchOptions
options
)
{
var
progress
=
new
FindReferencesProgressAdapter
(
project
.
Solution
,
context
,
options
);
return
SymbolFinder
.
FindReferencesAsync
(
symbol
,
project
.
Solution
,
progress
,
documents
:
null
,
options
,
context
.
CancellationToken
);
}
private
async
Task
<
bool
>
TryFindLiteralReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
var
cancellationToken
=
context
.
CancellationToken
;
cancellationToken
.
ThrowIfCancellationRequested
();
var
syntaxTree
=
await
document
.
GetRequiredSyntaxTreeAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
syntaxFacts
=
document
.
GetRequiredLanguageService
<
ISyntaxFactsService
>();
// Currently we only support FAR for numbers, strings and characters. We don't
// bother with true/false/null as those are likely to have way too many results
// to be useful.
var
token
=
await
syntaxTree
.
GetTouchingTokenAsync
(
position
,
t
=>
syntaxFacts
.
IsNumericLiteral
(
t
)
||
syntaxFacts
.
IsCharacterLiteral
(
t
)
||
syntaxFacts
.
IsStringLiteral
(
t
),
cancellationToken
).
ConfigureAwait
(
false
);
if
(
token
.
RawKind
==
0
)
{
return
false
;
}
// Searching for decimals not supported currently. Our index can only store 64bits
// for numeric values, and a decimal won't fit within that.
var
tokenValue
=
token
.
Value
;
if
(
tokenValue
==
null
||
tokenValue
is
decimal
)
return
false
;
if
(
token
.
Parent
is
null
)
return
false
;
var
semanticModel
=
await
document
.
GetRequiredSemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
symbol
=
semanticModel
.
GetSymbolInfo
(
token
.
Parent
).
Symbol
??
semanticModel
.
GetDeclaredSymbol
(
token
.
Parent
);
// Numeric labels are available in VB. In that case we want the normal FAR engine to
// do the searching. For these literals we want to find symbolic results and not
// numeric matches.
if
(
symbol
is
ILabelSymbol
)
return
false
;
// Use the literal to make the title. Trim literal if it's too long.
var
title
=
syntaxFacts
.
ConvertToSingleLine
(
token
.
Parent
).
ToString
();
if
(
title
.
Length
>=
10
)
{
title
=
title
.
Substring
(
0
,
10
)
+
"..."
;
}
var
searchTitle
=
string
.
Format
(
EditorFeaturesResources
.
_0_references
,
title
);
await
context
.
SetSearchTitleAsync
(
searchTitle
).
ConfigureAwait
(
false
);
var
solution
=
document
.
Project
.
Solution
;
// There will only be one 'definition' that all matching literal reference.
// So just create it now and report to the context what it is.
var
definition
=
DefinitionItem
.
CreateNonNavigableItem
(
ImmutableArray
.
Create
(
TextTags
.
StringLiteral
),
ImmutableArray
.
Create
(
new
TaggedText
(
TextTags
.
Text
,
searchTitle
)));
await
context
.
OnDefinitionFoundAsync
(
definition
).
ConfigureAwait
(
false
);
var
progressAdapter
=
new
FindLiteralsProgressAdapter
(
context
,
definition
);
// Now call into the underlying FAR engine to find reference. The FAR
// engine will push results into the 'progress' instance passed into it.
// We'll take those results, massage them, and forward them along to the
// FindUsagesContext instance we were given.
await
SymbolFinder
.
FindLiteralReferencesAsync
(
tokenValue
,
Type
.
GetTypeCode
(
tokenValue
.
GetType
()),
solution
,
progressAdapter
,
cancellationToken
).
ConfigureAwait
(
false
);
return
true
;
}
}
}
src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService_FindReferences.cs
0 → 100644
浏览文件 @
05f93e23
// 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.
#
nullable
enable
using
System
;
using
System.Collections.Immutable
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.FindUsages
;
using
Microsoft.CodeAnalysis.LanguageServices
;
using
Microsoft.CodeAnalysis.Remote
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.Editor.FindUsages
{
internal
abstract
partial
class
AbstractFindUsagesService
{
public
async
Task
FindReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
var
definitionTrackingContext
=
new
DefinitionTrackingContext
(
context
);
// Need ConfigureAwait(true) here so we get back to the UI thread before calling
// GetThirdPartyDefinitions. We need to call that on the UI thread to match behavior
// of how the language service always worked in the past.
//
// Any async calls before GetThirdPartyDefinitions must be ConfigureAwait(true).
await
FindLiteralOrSymbolReferencesAsync
(
document
,
position
,
definitionTrackingContext
).
ConfigureAwait
(
true
);
// After the FAR engine is done call into any third party extensions to see
// if they want to add results.
var
thirdPartyDefinitions
=
GetThirdPartyDefinitions
(
document
.
Project
.
Solution
,
definitionTrackingContext
.
GetDefinitions
(),
context
.
CancellationToken
);
// From this point on we can do ConfigureAwait(false) as we're not calling back
// into third parties anymore.
foreach
(
var
definition
in
thirdPartyDefinitions
)
{
// Don't need ConfigureAwait(true) here
await
context
.
OnDefinitionFoundAsync
(
definition
).
ConfigureAwait
(
false
);
}
}
private
async
Task
FindLiteralOrSymbolReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
// First, see if we're on a literal. If so search for literals in the solution with
// the same value.
var
found
=
await
TryFindLiteralReferencesAsync
(
document
,
position
,
context
).
ConfigureAwait
(
false
);
if
(
found
)
{
return
;
}
// Wasn't a literal. Try again as a symbol.
await
FindSymbolReferencesAsync
(
document
,
position
,
context
).
ConfigureAwait
(
false
);
}
private
ImmutableArray
<
DefinitionItem
>
GetThirdPartyDefinitions
(
Solution
solution
,
ImmutableArray
<
DefinitionItem
>
definitions
,
CancellationToken
cancellationToken
)
{
var
factory
=
solution
.
Workspace
.
Services
.
GetRequiredService
<
IDefinitionsAndReferencesFactory
>();
return
definitions
.
Select
(
d
=>
factory
.
GetThirdPartyDefinitionItem
(
solution
,
d
,
cancellationToken
))
.
WhereNotNull
()
.
ToImmutableArray
();
}
private
async
Task
FindSymbolReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
var
cancellationToken
=
context
.
CancellationToken
;
cancellationToken
.
ThrowIfCancellationRequested
();
// Find the symbol we want to search and the solution we want to search in.
var
symbolAndProjectOpt
=
await
FindUsagesHelpers
.
GetRelevantSymbolAndProjectAtPositionAsync
(
document
,
position
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
symbolAndProjectOpt
==
null
)
return
;
var
(
symbol
,
project
)
=
symbolAndProjectOpt
.
Value
;
await
FindSymbolReferencesAsync
(
context
,
symbol
,
project
).
ConfigureAwait
(
false
);
}
/// <summary>
/// Public helper that we use from features like ObjectBrowser which start with a symbol
/// and want to push all the references to it into the Streaming-Find-References window.
/// </summary>
public
static
async
Task
FindSymbolReferencesAsync
(
IFindUsagesContext
context
,
ISymbol
symbol
,
Project
project
)
{
var
solution
=
project
.
Solution
;
var
monikerUsagesService
=
solution
.
Workspace
.
Services
.
GetRequiredService
<
IFindSymbolMonikerUsagesService
>();
await
context
.
SetSearchTitleAsync
(
string
.
Format
(
EditorFeaturesResources
.
_0_references
,
FindUsagesHelpers
.
GetDisplayName
(
symbol
))).
ConfigureAwait
(
false
);
var
options
=
FindReferencesSearchOptions
.
GetFeatureOptionsForStartingSymbol
(
symbol
);
// Now call into the underlying FAR engine to find reference. The FAR
// engine will push results into the 'progress' instance passed into it.
// We'll take those results, massage them, and forward them along to the
// FindReferencesContext instance we were given.
var
normalFindReferencesTask
=
FindReferencesAsync
(
context
,
symbol
,
project
,
options
);
// Kick off work to search the online code index system in parallel
var
codeIndexReferencesTask
=
FindSymbolMonikerReferencesAsync
(
monikerUsagesService
,
symbol
,
context
);
await
Task
.
WhenAll
(
normalFindReferencesTask
,
codeIndexReferencesTask
).
ConfigureAwait
(
false
);
}
public
static
async
Task
FindReferencesAsync
(
IFindUsagesContext
context
,
ISymbol
symbol
,
Project
project
,
FindReferencesSearchOptions
options
)
{
var
cancellationToken
=
context
.
CancellationToken
;
var
solution
=
project
.
Solution
;
var
client
=
await
RemoteHostClient
.
TryGetClientAsync
(
solution
.
Workspace
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
client
!=
null
)
{
// Create a callback that we can pass to the server process to hear about the
// results as it finds them. When we hear about results we'll forward them to
// the 'progress' parameter which will then update the UI.
var
serverCallback
=
new
FindUsagesServerCallback
(
solution
,
context
);
var
success
=
await
client
.
TryRunRemoteAsync
(
WellKnownServiceHubServices
.
CodeAnalysisService
,
nameof
(
IRemoteFindUsagesService
.
FindReferencesAsync
),
solution
,
new
object
[]
{
SerializableSymbolAndProjectId
.
Create
(
symbol
,
project
,
cancellationToken
),
SerializableFindReferencesSearchOptions
.
Dehydrate
(
options
),
},
serverCallback
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
success
)
return
;
}
// Couldn't effectively search in OOP. Perform the search in-process.
await
FindReferencesInCurrentProcessAsync
(
context
,
symbol
,
project
,
options
).
ConfigureAwait
(
false
);
}
private
static
Task
FindReferencesInCurrentProcessAsync
(
IFindUsagesContext
context
,
ISymbol
symbol
,
Project
project
,
FindReferencesSearchOptions
options
)
{
var
progress
=
new
FindReferencesProgressAdapter
(
project
.
Solution
,
context
,
options
);
return
SymbolFinder
.
FindReferencesAsync
(
symbol
,
project
.
Solution
,
progress
,
documents
:
null
,
options
,
context
.
CancellationToken
);
}
private
async
Task
<
bool
>
TryFindLiteralReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
var
cancellationToken
=
context
.
CancellationToken
;
cancellationToken
.
ThrowIfCancellationRequested
();
var
syntaxTree
=
await
document
.
GetRequiredSyntaxTreeAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
syntaxFacts
=
document
.
GetRequiredLanguageService
<
ISyntaxFactsService
>();
// Currently we only support FAR for numbers, strings and characters. We don't
// bother with true/false/null as those are likely to have way too many results
// to be useful.
var
token
=
await
syntaxTree
.
GetTouchingTokenAsync
(
position
,
t
=>
syntaxFacts
.
IsNumericLiteral
(
t
)
||
syntaxFacts
.
IsCharacterLiteral
(
t
)
||
syntaxFacts
.
IsStringLiteral
(
t
),
cancellationToken
).
ConfigureAwait
(
false
);
if
(
token
.
RawKind
==
0
)
{
return
false
;
}
// Searching for decimals not supported currently. Our index can only store 64bits
// for numeric values, and a decimal won't fit within that.
var
tokenValue
=
token
.
Value
;
if
(
tokenValue
==
null
||
tokenValue
is
decimal
)
return
false
;
if
(
token
.
Parent
is
null
)
return
false
;
var
semanticModel
=
await
document
.
GetRequiredSemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
symbol
=
semanticModel
.
GetSymbolInfo
(
token
.
Parent
).
Symbol
??
semanticModel
.
GetDeclaredSymbol
(
token
.
Parent
);
// Numeric labels are available in VB. In that case we want the normal FAR engine to
// do the searching. For these literals we want to find symbolic results and not
// numeric matches.
if
(
symbol
is
ILabelSymbol
)
return
false
;
// Use the literal to make the title. Trim literal if it's too long.
var
title
=
syntaxFacts
.
ConvertToSingleLine
(
token
.
Parent
).
ToString
();
if
(
title
.
Length
>=
10
)
{
title
=
title
.
Substring
(
0
,
10
)
+
"..."
;
}
var
searchTitle
=
string
.
Format
(
EditorFeaturesResources
.
_0_references
,
title
);
await
context
.
SetSearchTitleAsync
(
searchTitle
).
ConfigureAwait
(
false
);
var
solution
=
document
.
Project
.
Solution
;
// There will only be one 'definition' that all matching literal reference.
// So just create it now and report to the context what it is.
var
definition
=
DefinitionItem
.
CreateNonNavigableItem
(
ImmutableArray
.
Create
(
TextTags
.
StringLiteral
),
ImmutableArray
.
Create
(
new
TaggedText
(
TextTags
.
Text
,
searchTitle
)));
await
context
.
OnDefinitionFoundAsync
(
definition
).
ConfigureAwait
(
false
);
var
progressAdapter
=
new
FindLiteralsProgressAdapter
(
context
,
definition
);
// Now call into the underlying FAR engine to find reference. The FAR
// engine will push results into the 'progress' instance passed into it.
// We'll take those results, massage them, and forward them along to the
// FindUsagesContext instance we were given.
await
SymbolFinder
.
FindLiteralReferencesAsync
(
tokenValue
,
Type
.
GetTypeCode
(
tokenValue
.
GetType
()),
solution
,
progressAdapter
,
cancellationToken
).
ConfigureAwait
(
false
);
return
true
;
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录