Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
799b963c
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,发现更多精彩内容 >>
提交
799b963c
编写于
1月 31, 2017
作者:
C
CyrusNajmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Don't group by definition when presenting result for FindImplementations or GoToDef.
上级
2e1cb224
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
492 addition
and
321 deletion
+492
-321
src/EditorFeatures/Core/FindReferences/FindReferencesCommandHandler.cs
...tures/Core/FindReferences/FindReferencesCommandHandler.cs
+1
-1
src/EditorFeatures/Core/GoToDefinition/GoToDefinitionHelpers.cs
...itorFeatures/Core/GoToDefinition/GoToDefinitionHelpers.cs
+1
-5
src/EditorFeatures/Core/GoToImplementation/GoToImplementationCommandHandler.cs
...re/GoToImplementation/GoToImplementationCommandHandler.cs
+1
-2
src/EditorFeatures/Core/Host/IStreamingFindReferencesPresenter.cs
...orFeatures/Core/Host/IStreamingFindReferencesPresenter.cs
+4
-4
src/VisualStudio/Core/Next/FindReferences/StreamingFindUsagesPresenter.DocumentLocationEntry.cs
...ces/StreamingFindUsagesPresenter.DocumentLocationEntry.cs
+69
-27
src/VisualStudio/Core/Next/FindReferences/StreamingFindUsagesPresenter.RoslynDefinitionBucket.cs
...es/StreamingFindUsagesPresenter.RoslynDefinitionBucket.cs
+2
-2
src/VisualStudio/Core/Next/FindReferences/StreamingFindUsagesPresenter.TableDataSourceFindUsagesContext.cs
...ngFindUsagesPresenter.TableDataSourceFindUsagesContext.cs
+409
-277
src/VisualStudio/Core/Next/FindReferences/StreamingFindUsagesPresenter.cs
.../Core/Next/FindReferences/StreamingFindUsagesPresenter.cs
+5
-3
未找到文件。
src/EditorFeatures/Core/FindReferences/FindReferencesCommandHandler.cs
浏览文件 @
799b963c
...
...
@@ -126,7 +126,7 @@ private IStreamingFindUsagesPresenter GetStreamingPresenter()
// Let the presented know we're starging a search. It will give us back
// the context object that the FAR service will push results into.
var
context
=
presenter
.
StartSearch
(
EditorFeaturesResources
.
Find_References
,
alwaysShowDeclarations
:
fals
e
);
EditorFeaturesResources
.
Find_References
,
canShowReferences
:
tru
e
);
await
findUsagesService
.
FindReferencesAsync
(
document
,
caretPosition
,
context
).
ConfigureAwait
(
false
);
// Note: we don't need to put this in a finally. The only time we might not hit
...
...
src/EditorFeatures/Core/GoToDefinition/GoToDefinitionHelpers.cs
浏览文件 @
799b963c
...
...
@@ -3,15 +3,12 @@
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Runtime.InteropServices
;
using
System.Threading
;
using
Microsoft.CodeAnalysis.Editor.FindReferences
;
using
Microsoft.CodeAnalysis.Editor.FindUsages
;
using
Microsoft.CodeAnalysis.Editor.Host
;
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.FindUsages
;
using
Microsoft.CodeAnalysis.Navigation
;
using
Microsoft.CodeAnalysis.Options
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.Editor.GoToDefinition
...
...
@@ -75,8 +72,7 @@ internal static class GoToDefinitionHelpers
FindUsagesHelpers
.
GetDisplayName
(
symbol
));
return
presenter
.
TryNavigateToOrPresentItemsAsync
(
title
,
definitions
.
ToImmutableAndFree
(),
alwaysShowDeclarations
:
true
).
WaitAndGetResult
(
cancellationToken
);
title
,
definitions
.
ToImmutableAndFree
()).
WaitAndGetResult
(
cancellationToken
);
}
private
static
IStreamingFindUsagesPresenter
GetFindUsagesPresenter
(
...
...
src/EditorFeatures/Core/GoToImplementation/GoToImplementationCommandHandler.cs
浏览文件 @
799b963c
...
...
@@ -136,8 +136,7 @@ public void ExecuteCommand(GoToImplementationCommandArgs args, Action nextHandle
var
definitionItems
=
goToImplContext
.
GetDefinitions
();
streamingPresenter
.
TryNavigateToOrPresentItemsAsync
(
goToImplContext
.
SearchTitle
,
definitionItems
,
alwaysShowDeclarations
:
true
).
Wait
(
cancellationToken
);
goToImplContext
.
SearchTitle
,
definitionItems
).
Wait
(
cancellationToken
);
}
private
IStreamingFindUsagesPresenter
GetStreamingPresenter
()
...
...
src/EditorFeatures/Core/Host/IStreamingFindReferencesPresenter.cs
浏览文件 @
799b963c
...
...
@@ -21,7 +21,7 @@ internal interface IStreamingFindUsagesPresenter
/// search completes <see cref="FindUsagesContext.OnCompletedAsync"/> should be called.
/// etc. etc.
/// </summary>
FindUsagesContext
StartSearch
(
string
title
,
bool
alwaysShowDeclaration
s
);
FindUsagesContext
StartSearch
(
string
title
,
bool
canShowReference
s
);
}
internal
static
class
IStreamingFindUsagesPresenterExtensions
...
...
@@ -31,8 +31,8 @@ internal static class IStreamingFindUsagesPresenterExtensions
/// items to the user.
/// </summary>
public
static
async
Task
<
bool
>
TryNavigateToOrPresentItemsAsync
(
this
IStreamingFindUsagesPresenter
presenter
,
string
title
,
ImmutableArray
<
DefinitionItem
>
items
,
bool
alwaysShowDeclaration
s
)
this
IStreamingFindUsagesPresenter
presenter
,
string
title
,
ImmutableArray
<
DefinitionItem
>
item
s
)
{
// Ignore any definitions that we can't navigate to.
var
definitions
=
items
.
WhereAsArray
(
d
=>
d
.
CanNavigateTo
());
...
...
@@ -66,7 +66,7 @@ internal static class IStreamingFindUsagesPresenterExtensions
// We have multiple definitions, or we have definitions with multiple locations.
// Present this to the user so they can decide where they want to go to.
var
context
=
presenter
.
StartSearch
(
title
,
alwaysShowDeclarations
);
var
context
=
presenter
.
StartSearch
(
title
,
canShowReferences
:
false
);
foreach
(
var
definition
in
nonExternalItems
)
{
await
context
.
OnDefinitionFoundAsync
(
definition
).
ConfigureAwait
(
false
);
...
...
src/VisualStudio/Core/Next/FindReferences/StreamingFindUsagesPresenter.DocumentLocationEntry.cs
浏览文件 @
799b963c
...
...
@@ -27,60 +27,102 @@ namespace Microsoft.VisualStudio.LanguageServices.FindUsages
{
internal
partial
class
StreamingFindUsagesPresenter
{
private
class
DocumentSpanEntry
:
Entry
private
abstract
class
Abstract
DocumentSpanEntry
:
Entry
{
private
readonly
TableDataSourceFindUsagesContext
_context
;
private
readonly
Abstract
TableDataSourceFindUsagesContext
_context
;
private
readonly
DocumentSpan
_documentSpan
;
private
readonly
bool
_isDefinitionLocation
;
private
readonly
object
_boxedProjectGuid
;
private
readonly
SourceText
_sourceText
;
private
readonly
ClassifiedSpansAndHighlightSpan
_classifiedSpans
;
protected
readonly
SourceText
_sourceText
;
p
ublic
DocumentSpanEntry
(
TableDataSourceFindUsagesContext
context
,
p
rotected
Abstract
DocumentSpanEntry
(
Abstract
TableDataSourceFindUsagesContext
context
,
RoslynDefinitionBucket
definitionBucket
,
DocumentSpan
documentSpan
,
bool
isDefinitionLocation
,
Guid
projectGuid
,
SourceText
sourceText
,
ClassifiedSpansAndHighlightSpan
classifiedSpans
)
SourceText
sourceText
)
:
base
(
definitionBucket
)
{
_context
=
context
;
_documentSpan
=
documentSpan
;
_isDefinitionLocation
=
isDefinitionLocation
;
_boxedProjectGuid
=
projectGuid
;
_sourceText
=
sourceText
;
_classifiedSpans
=
classifiedSpans
;
}
pr
ivate
StreamingFindUsagesPresenter
Presenter
=>
_context
.
Presenter
;
pr
otected
StreamingFindUsagesPresenter
Presenter
=>
_context
.
Presenter
;
pr
ivate
Document
Document
=>
_documentSpan
.
Document
;
pr
ivate
TextSpan
SourceSpan
=>
_documentSpan
.
SourceSpan
;
pr
otected
Document
Document
=>
_documentSpan
.
Document
;
pr
otected
TextSpan
SourceSpan
=>
_documentSpan
.
SourceSpan
;
protected
override
object
GetValueWorker
(
string
keyName
)
{
switch
(
keyName
)
{
case
StandardTableKeyNames
.
DocumentName
:
return
Document
.
FilePath
;
case
StandardTableKeyNames
.
Line
:
return
_sourceText
.
Lines
.
GetLinePosition
(
SourceSpan
.
Start
).
Line
;
case
StandardTableKeyNames
.
Column
:
return
_sourceText
.
Lines
.
GetLinePosition
(
SourceSpan
.
Start
).
Character
;
case
StandardTableKeyNames
.
ProjectName
:
return
Document
.
Project
.
Name
;
case
StandardTableKeyNames
.
ProjectGuid
:
return
_boxedProjectGuid
;
case
StandardTableKeyNames
.
Text
:
return
_sourceText
.
Lines
.
GetLineFromPosition
(
SourceSpan
.
Start
).
ToString
().
Trim
();
case
StandardTableKeyNames
.
DocumentName
:
return
Document
.
FilePath
;
case
StandardTableKeyNames
.
Line
:
return
_sourceText
.
Lines
.
GetLinePosition
(
SourceSpan
.
Start
).
Line
;
case
StandardTableKeyNames
.
Column
:
return
_sourceText
.
Lines
.
GetLinePosition
(
SourceSpan
.
Start
).
Character
;
case
StandardTableKeyNames
.
ProjectName
:
return
Document
.
Project
.
Name
;
case
StandardTableKeyNames
.
ProjectGuid
:
return
_boxedProjectGuid
;
case
StandardTableKeyNames
.
Text
:
return
_sourceText
.
Lines
.
GetLineFromPosition
(
SourceSpan
.
Start
).
ToString
().
Trim
();
}
return
null
;
}
}
private
class
DefinitionItemEntry
:
AbstractDocumentSpanEntry
{
public
DefinitionItemEntry
(
AbstractTableDataSourceFindUsagesContext
context
,
RoslynDefinitionBucket
definitionBucket
,
DocumentSpan
documentSpan
,
Guid
projectGuid
,
SourceText
sourceText
)
:
base
(
context
,
definitionBucket
,
documentSpan
,
projectGuid
,
sourceText
)
{
}
public
override
bool
TryCreateColumnContent
(
string
columnName
,
out
FrameworkElement
content
)
{
if
(
columnName
==
StandardTableColumnDefinitions2
.
LineText
)
{
var
inlines
=
DefinitionBucket
.
DefinitionItem
.
DisplayParts
.
ToInlines
(
Presenter
.
_typeMap
);
var
textBlock
=
inlines
.
ToTextBlock
(
Presenter
.
_typeMap
,
wrap
:
false
);
content
=
textBlock
;
return
true
;
}
content
=
null
;
return
false
;
}
}
private
class
DocumentSpanEntry
:
AbstractDocumentSpanEntry
{
private
readonly
bool
_isDefinitionLocation
;
private
readonly
ClassifiedSpansAndHighlightSpan
_classifiedSpans
;
public
DocumentSpanEntry
(
AbstractTableDataSourceFindUsagesContext
context
,
RoslynDefinitionBucket
definitionBucket
,
DocumentSpan
documentSpan
,
bool
isDefinitionLocation
,
Guid
projectGuid
,
SourceText
sourceText
,
ClassifiedSpansAndHighlightSpan
classifiedSpans
)
:
base
(
context
,
definitionBucket
,
documentSpan
,
projectGuid
,
sourceText
)
{
_isDefinitionLocation
=
isDefinitionLocation
;
_classifiedSpans
=
classifiedSpans
;
}
public
override
bool
TryCreateColumnContent
(
string
columnName
,
out
FrameworkElement
content
)
{
...
...
src/VisualStudio/Core/Next/FindReferences/StreamingFindUsagesPresenter.RoslynDefinitionBucket.cs
浏览文件 @
799b963c
...
...
@@ -17,13 +17,13 @@ internal partial class StreamingFindUsagesPresenter
private
class
RoslynDefinitionBucket
:
DefinitionBucket
,
ISupportsNavigation
{
private
readonly
StreamingFindUsagesPresenter
_presenter
;
private
readonly
TableDataSourceFindUsagesContext
_context
;
private
readonly
Abstract
TableDataSourceFindUsagesContext
_context
;
public
readonly
DefinitionItem
DefinitionItem
;
public
RoslynDefinitionBucket
(
StreamingFindUsagesPresenter
presenter
,
TableDataSourceFindUsagesContext
context
,
Abstract
TableDataSourceFindUsagesContext
context
,
DefinitionItem
definitionItem
)
:
base
(
name
:
definitionItem
.
DisplayParts
.
JoinText
()
+
" "
+
definitionItem
.
GetHashCode
(),
sourceTypeIdentifier
:
context
.
SourceTypeIdentifier
,
...
...
src/VisualStudio/Core/Next/FindReferences/StreamingFindUsagesPresenter.TableDataSourceFindUsagesContext.cs
浏览文件 @
799b963c
...
...
@@ -26,7 +26,7 @@ namespace Microsoft.VisualStudio.LanguageServices.FindUsages
{
internal
partial
class
StreamingFindUsagesPresenter
{
private
class
TableDataSourceFindUsagesContext
:
private
abstract
class
Abstract
TableDataSourceFindUsagesContext
:
FindUsagesContext
,
ITableDataSource
,
ITableEntriesSnapshotFactory
{
private
readonly
CancellationTokenSource
_cancellationTokenSource
=
new
CancellationTokenSource
();
...
...
@@ -35,10 +35,9 @@ private class TableDataSourceFindUsagesContext :
public
readonly
StreamingFindUsagesPresenter
Presenter
;
private
readonly
IFindAllReferencesWindow
_findReferencesWindow
;
private
readonly
IWpfTableControl2
_tableControl
;
private
readonly
bool
_alwaysIncludeDeclarations
;
protected
readonly
IWpfTableControl2
_tableControl
;
pr
ivate
readonly
object
_gate
=
new
object
();
pr
otected
readonly
object
_gate
=
new
object
();
#
region
Fields
that
should
be
locked
by
_gate
...
...
@@ -49,7 +48,7 @@ private class TableDataSourceFindUsagesContext :
/// us to not display it if it has no references, and we don't run into any
/// references for it (common with implicitly declared symbols).
/// </summary>
pr
ivate
readonly
List
<
DefinitionItem
>
_definitions
=
new
List
<
DefinitionItem
>();
pr
otected
readonly
List
<
DefinitionItem
>
_definitions
=
new
List
<
DefinitionItem
>();
/// <summary>
/// We will hear about the same definition over and over again. i.e. for each reference
...
...
@@ -70,23 +69,21 @@ private class TableDataSourceFindUsagesContext :
/// </summary>
private
bool
_currentlyGroupingByDefinition
;
pr
ivate
ImmutableList
<
Entry
>
_entriesWithDeclarations
=
ImmutableList
<
Entry
>.
Empty
;
pr
ivate
ImmutableList
<
Entry
>
_entriesWithoutDeclarations
=
ImmutableList
<
Entry
>.
Empty
;
pr
otected
ImmutableList
<
Entry
>
_entriesWhenNotGroupingByDefinition
=
ImmutableList
<
Entry
>.
Empty
;
pr
otected
ImmutableList
<
Entry
>
_entriesWhenGroupingByDefinition
=
ImmutableList
<
Entry
>.
Empty
;
private
TableEntriesSnapshot
_lastSnapshot
;
public
int
CurrentVersionNumber
{
get
;
pr
ivate
set
;
}
public
int
CurrentVersionNumber
{
get
;
pr
otected
set
;
}
#
endregion
p
ublic
TableDataSourceFindUsagesContext
(
p
rotected
Abstract
TableDataSourceFindUsagesContext
(
StreamingFindUsagesPresenter
presenter
,
IFindAllReferencesWindow
findReferencesWindow
,
bool
alwaysIncludeDeclarations
)
IFindAllReferencesWindow
findReferencesWindow
)
{
presenter
.
AssertIsForeground
();
Presenter
=
presenter
;
_alwaysIncludeDeclarations
=
alwaysIncludeDeclarations
;
_findReferencesWindow
=
findReferencesWindow
;
_tableControl
=
(
IWpfTableControl2
)
findReferencesWindow
.
TableControl
;
_tableControl
.
GroupingsChanged
+=
OnTableControlGroupingsChanged
;
...
...
@@ -110,6 +107,9 @@ private class TableDataSourceFindUsagesContext :
Debug
.
Assert
(
_tableDataSink
!=
null
);
}
protected
void
NotifyChange
()
=>
_tableDataSink
.
FactorySnapshotChanged
(
this
);
private
void
OnFindReferencesWindowClosed
(
object
sender
,
EventArgs
e
)
{
Presenter
.
AssertIsForeground
();
...
...
@@ -172,7 +172,7 @@ internal void OnSubscriptionDisposed()
CancelSearch
();
}
public
override
CancellationToken
CancellationToken
=>
_cancellationTokenSource
.
Token
;
public
sealed
override
CancellationToken
CancellationToken
=>
_cancellationTokenSource
.
Token
;
#
region
ITableDataSource
...
...
@@ -199,293 +199,50 @@ public IDisposable Subscribe(ITableDataSink sink)
#
region
FindUsagesContext
overrides
.
public
override
void
SetSearchTitle
(
string
title
)
public
sealed
override
void
SetSearchTitle
(
string
title
)
=>
_findReferencesWindow
.
Title
=
title
;
public
override
async
Task
OnCompletedAsync
()
public
sealed
override
async
Task
OnCompletedAsync
()
{
// Now that we know the search is over, create and display any error messages
// for definitions that were not found.
await
CreateMissingReferenceEntriesIfNecessaryAsync
().
ConfigureAwait
(
false
);
await
CreateNoResultsFoundEntryIfNecessaryAsync
().
ConfigureAwait
(
false
);
await
OnCompletedAsyncWorkerAsync
().
ConfigureAwait
(
false
);
_tableDataSink
.
IsStable
=
true
;
}
private
async
Task
CreateNoResultsFoundEntryIfNecessaryAsync
()
{
bool
noDefinitions
;
lock
(
_gate
)
{
noDefinitions
=
this
.
_definitions
.
Count
==
0
;
}
if
(
noDefinitions
)
{
// Create a fake definition/reference called "search found no results"
await
OnEntryFoundAsync
(
NoResultsDefinitionItem
,
bucket
=>
SimpleMessageEntry
.
CreateAsync
(
bucket
,
ServicesVisualStudioNextResources
.
Search_found_no_results
),
addToEntriesWithDeclarations
:
true
,
addToEntriesWithoutDeclarations
:
true
).
ConfigureAwait
(
false
);
}
}
private
static
readonly
DefinitionItem
NoResultsDefinitionItem
=
DefinitionItem
.
CreateNonNavigableItem
(
GlyphTags
.
GetTags
(
Glyph
.
StatusInformation
),
ImmutableArray
.
Create
(
new
TaggedText
(
TextTags
.
Text
,
ServicesVisualStudioNextResources
.
Search_found_no_results
)));
private
async
Task
CreateMissingReferenceEntriesIfNecessaryAsync
()
{
await
CreateMissingReferenceEntriesIfNecessaryAsync
(
withDeclarations
:
true
).
ConfigureAwait
(
false
);
await
CreateMissingReferenceEntriesIfNecessaryAsync
(
withDeclarations
:
false
).
ConfigureAwait
(
false
);
}
protected
abstract
Task
OnCompletedAsyncWorkerAsync
();
private
async
Task
CreateMissingReferenceEntriesIfNecessaryAsync
(
bool
withDeclarations
)
{
// Go through and add dummy entries for any definitions that
// that we didn't find any references for.
var
definitions
=
GetDefinitionsToCreateMissingReferenceItemsFor
(
withDeclarations
);
foreach
(
var
definition
in
definitions
)
{
// Create a fake reference to this definition that says
// "no references found to <symbolname>".
await
OnEntryFoundAsync
(
definition
,
bucket
=>
SimpleMessageEntry
.
CreateAsync
(
bucket
,
GetMessage
(
bucket
.
DefinitionItem
)),
addToEntriesWithDeclarations
:
withDeclarations
,
addToEntriesWithoutDeclarations
:
!
withDeclarations
).
ConfigureAwait
(
false
);
}
}
private
static
string
GetMessage
(
DefinitionItem
definition
)
{
if
(
definition
.
IsExternal
)
{
return
ServicesVisualStudioNextResources
.
External_reference_found
;
}
return
string
.
Format
(
ServicesVisualStudioNextResources
.
No_references_found_to_0
,
definition
.
NameDisplayParts
.
JoinText
());
}
private
ImmutableArray
<
DefinitionItem
>
GetDefinitionsToCreateMissingReferenceItemsFor
(
bool
withDeclarations
)
{
lock
(
_gate
)
{
var
entries
=
withDeclarations
?
_entriesWithDeclarations
:
_entriesWithoutDeclarations
;
// Find any definitions that we didn't have any references to. But only show
// them if they want to be displayed without any references. This will
// ensure that we still see things like overrides and whatnot, but we
// won't show property-accessors.
var
seenDefinitions
=
entries
.
Select
(
r
=>
r
.
DefinitionBucket
.
DefinitionItem
).
ToSet
();
var
q
=
from
definition
in
_definitions
where
!
seenDefinitions
.
Contains
(
definition
)
&&
definition
.
DisplayIfNoReferences
select
definition
;
// If we find at least one of these types of definitions, then just return those.
var
result
=
ImmutableArray
.
CreateRange
(
q
);
if
(
result
.
Length
>
0
)
{
return
result
;
}
// We found no definitions that *want* to be displayed. However, we still
// want to show something. So, if necessary, show at lest the first definition
// even if we found no references and even if it would prefer to not be seen.
if
(
entries
.
Count
==
0
&&
_definitions
.
Count
>
0
)
{
return
ImmutableArray
.
Create
(
_definitions
.
First
());
}
return
ImmutableArray
<
DefinitionItem
>.
Empty
;
}
}
public
override
async
Task
OnDefinitionFoundAsync
(
DefinitionItem
definition
)
public
sealed
override
Task
OnDefinitionFoundAsync
(
DefinitionItem
definition
)
{
lock
(
_gate
)
{
_definitions
.
Add
(
definition
);
}
// If this is a definition we always want to show, then create entries
// for all the declaration locations immediately. Otherwise, we'll
// create them on demand when we hear about references for this definition.
if
(
definition
.
DisplayIfNoReferences
)
{
await
AddDeclarationEntriesAsync
(
definition
).
ConfigureAwait
(
false
);
}
}
private
bool
HasDeclarationEntries
(
DefinitionItem
definition
)
{
lock
(
_gate
)
{
return
_entriesWithDeclarations
.
Any
(
e
=>
e
.
DefinitionBucket
.
DefinitionItem
==
definition
);
}
}
private
async
Task
AddDeclarationEntriesAsync
(
DefinitionItem
definition
)
{
CancellationToken
.
ThrowIfCancellationRequested
();
// Don't do anything if we already have declaration entries for this definition
// (i.e. another thread beat us to this).
if
(
HasDeclarationEntries
(
definition
))
{
return
;
}
var
definitionBucket
=
GetOrCreateDefinitionBucket
(
definition
);
// We could do this inside the lock. but that would mean async activity in a
// lock, and i'd like to avoid that. That does mean that we might do extra
// work if multiple threads end up down htis path. But only one of them will
// win when we access the lock below.
var
declarations
=
ArrayBuilder
<
Entry
>.
GetInstance
();
foreach
(
var
declarationLocation
in
definition
.
SourceSpans
)
{
var
definitionEntry
=
await
CreateDocumentLocationEntryAsync
(
definitionBucket
,
declarationLocation
,
isDefinitionLocation
:
true
).
ConfigureAwait
(
false
);
if
(
definitionEntry
!=
null
)
{
declarations
.
Add
(
definitionEntry
);
}
}
lock
(
_gate
)
{
// Do one final check to ensure that no other thread beat us here.
if
(!
HasDeclarationEntries
(
definition
))
{
// We only include declaration entries in the entries we show when
// not grouping by definition.
_entriesWithDeclarations
=
_entriesWithDeclarations
.
AddRange
(
declarations
);
CurrentVersionNumber
++;
}
}
declarations
.
Free
();
// Let all our subscriptions know that we've updated.
_tableDataSink
.
FactorySnapshotChanged
(
this
);
return
OnDefinitionFoundWorkerAsync
(
definition
);
}
public
override
Task
OnReferenceFoundAsync
(
SourceReferenceItem
reference
)
{
// Normal references go into both sets of entries.
return
OnEntryFoundAsync
(
reference
.
Definition
,
bucket
=>
CreateDocumentLocationEntryAsync
(
bucket
,
reference
.
SourceSpan
,
isDefinitionLocation
:
false
),
addToEntriesWithDeclarations
:
true
,
addToEntriesWithoutDeclarations
:
true
);
}
private
async
Task
OnEntryFoundAsync
(
DefinitionItem
definition
,
Func
<
RoslynDefinitionBucket
,
Task
<
Entry
>>
createEntryAsync
,
bool
addToEntriesWithDeclarations
,
bool
addToEntriesWithoutDeclarations
)
{
Debug
.
Assert
(
addToEntriesWithDeclarations
||
addToEntriesWithoutDeclarations
);
CancellationToken
.
ThrowIfCancellationRequested
();
// First find the bucket corresponding to our definition.
var
definitionBucket
=
GetOrCreateDefinitionBucket
(
definition
);
var
entry
=
await
createEntryAsync
(
definitionBucket
).
ConfigureAwait
(
false
);
// Ok, we got a *reference* to some definition item. This may have been
// a reference for some definition that we haven't created any declaration
// entries for (i.e. becuase it had DisplayIfNoReferences = false). Because
// we've now found a reference, we want to make sure all its declaration
// entries are added.
await
AddDeclarationEntriesAsync
(
definition
).
ConfigureAwait
(
false
);
protected
abstract
Task
OnDefinitionFoundWorkerAsync
(
DefinitionItem
definition
);
lock
(
_gate
)
{
// Once we can make the new entry, add it to the appropriate list.
if
(
addToEntriesWithDeclarations
)
{
_entriesWithDeclarations
=
_entriesWithDeclarations
.
Add
(
entry
);
}
if
(
addToEntriesWithoutDeclarations
)
{
_entriesWithoutDeclarations
=
_entriesWithoutDeclarations
.
Add
(
entry
);
}
CurrentVersionNumber
++;
}
// Let all our subscriptions know that we've updated.
_tableDataSink
.
FactorySnapshotChanged
(
this
);
}
private
async
Task
<
Entry
>
CreateDocumentLocationEntryAsync
(
protected
async
Task
<
Entry
>
CreateDocumentLocationEntryAsync
(
RoslynDefinitionBucket
definitionBucket
,
DocumentSpan
documentSpan
,
bool
isDefinitionLocation
)
{
var
document
=
documentSpan
.
Document
;
var
(
guid
,
sourceText
)
=
await
GetGuidAndSourceTextAsync
(
document
).
ConfigureAwait
(
false
);
// The FAR system needs to know the guid for the project that a def/reference is
// from (to support features like filtering). Normally that would mean we could
// only support this from a VisualStudioWorkspace. However, we want till work
// in cases lke Any-Code (which does not use a VSWorkspace). So we are tolerant
// when we have another type of workspace. This means we will show results, but
// certain features (like filtering) may not work in that context.
var
workspace
=
document
.
Project
.
Solution
.
Workspace
as
VisualStudioWorkspaceImpl
;
var
guid
=
workspace
?.
GetHostProject
(
document
.
Project
.
Id
)?.
Guid
??
Guid
.
Empty
;
var
sourceText
=
await
document
.
GetTextAsync
(
CancellationToken
).
ConfigureAwait
(
false
);
var
referenceSpan
=
documentSpan
.
SourceSpan
;
var
lineSpan
=
GetLineSpanForReference
(
sourceText
,
referenceSpan
);
var
narrowSpan
=
documentSpan
.
SourceSpan
;
var
lineSpan
=
GetLineSpanForReference
(
sourceText
,
narrowSpan
);
var
taggedLineParts
=
await
GetTaggedTextFor
ReferenceAsync
(
document
,
reference
Span
,
lineSpan
).
ConfigureAwait
(
false
);
var
taggedLineParts
=
await
GetTaggedTextFor
DocumentRegionAsync
(
document
,
narrow
Span
,
lineSpan
).
ConfigureAwait
(
false
);
return
new
DocumentSpanEntry
(
this
,
definitionBucket
,
documentSpan
,
isDefinitionLocation
,
guid
,
sourceText
,
taggedLineParts
);
}
private
TextSpan
GetLineSpanForReference
(
SourceText
sourceText
,
TextSpan
referenceSpan
)
{
var
sourceLine
=
sourceText
.
Lines
.
GetLineFromPosition
(
referenceSpan
.
Start
);
var
firstNonWhitespacePosition
=
sourceLine
.
GetFirstNonWhitespacePosition
().
Value
;
return
TextSpan
.
FromBounds
(
firstNonWhitespacePosition
,
sourceLine
.
End
);
}
private
TextSpan
GetRegionSpanForReference
(
SourceText
sourceText
,
TextSpan
referenceSpan
)
{
const
int
AdditionalLineCountPerSide
=
3
;
var
lineNumber
=
sourceText
.
Lines
.
GetLineFromPosition
(
referenceSpan
.
Start
).
LineNumber
;
var
firstLineNumber
=
Math
.
Max
(
0
,
lineNumber
-
AdditionalLineCountPerSide
);
var
lastLineNumber
=
Math
.
Min
(
sourceText
.
Lines
.
Count
-
1
,
lineNumber
+
AdditionalLineCountPerSide
);
return
TextSpan
.
FromBounds
(
sourceText
.
Lines
[
firstLineNumber
].
Start
,
sourceText
.
Lines
[
lastLineNumber
].
End
);
}
private
async
Task
<
ClassifiedSpansAndHighlightSpan
>
GetTaggedTextForReferenceAsync
(
Document
document
,
TextSpan
referenceSpan
,
TextSpan
widenedSpan
)
private
async
Task
<
ClassifiedSpansAndHighlightSpan
>
GetTaggedTextForDocumentRegionAsync
(
Document
document
,
TextSpan
narrowSpan
,
TextSpan
widenedSpan
)
{
var
classificationService
=
document
.
GetLanguageService
<
IEditorClassificationService
>();
if
(
classificationService
==
null
)
...
...
@@ -515,8 +272,8 @@ private TextSpan GetRegionSpanForReference(SourceText sourceText, TextSpan refer
syntaxSpans
,
semanticSpans
,
widenedSpan
,
sourceText
);
var
highlightSpan
=
new
TextSpan
(
start
:
reference
Span
.
Start
-
widenedSpan
.
Start
,
length
:
reference
Span
.
Length
);
start
:
narrow
Span
.
Start
-
widenedSpan
.
Start
,
length
:
narrow
Span
.
Length
);
return
new
ClassifiedSpansAndHighlightSpan
(
classifiedSpans
,
highlightSpan
);
}
...
...
@@ -527,6 +284,27 @@ private TextSpan GetRegionSpanForReference(SourceText sourceText, TextSpan refer
}
}
private
TextSpan
GetLineSpanForReference
(
SourceText
sourceText
,
TextSpan
referenceSpan
)
{
var
sourceLine
=
sourceText
.
Lines
.
GetLineFromPosition
(
referenceSpan
.
Start
);
var
firstNonWhitespacePosition
=
sourceLine
.
GetFirstNonWhitespacePosition
().
Value
;
return
TextSpan
.
FromBounds
(
firstNonWhitespacePosition
,
sourceLine
.
End
);
}
private
TextSpan
GetRegionSpanForReference
(
SourceText
sourceText
,
TextSpan
referenceSpan
)
{
const
int
AdditionalLineCountPerSide
=
3
;
var
lineNumber
=
sourceText
.
Lines
.
GetLineFromPosition
(
referenceSpan
.
Start
).
LineNumber
;
var
firstLineNumber
=
Math
.
Max
(
0
,
lineNumber
-
AdditionalLineCountPerSide
);
var
lastLineNumber
=
Math
.
Min
(
sourceText
.
Lines
.
Count
-
1
,
lineNumber
+
AdditionalLineCountPerSide
);
return
TextSpan
.
FromBounds
(
sourceText
.
Lines
[
firstLineNumber
].
Start
,
sourceText
.
Lines
[
lastLineNumber
].
End
);
}
private
ImmutableArray
<
ClassifiedSpan
>
MergeClassifiedSpans
(
List
<
ClassifiedSpan
>
syntaxSpans
,
List
<
ClassifiedSpan
>
semanticSpans
,
TextSpan
widenedSpan
,
SourceText
sourceText
)
...
...
@@ -668,7 +446,12 @@ private bool IsClassifiedAsText(ClassifiedSpan partAndSpan)
return
partAndSpan
.
ClassificationType
==
ClassificationTypeNames
.
Text
;
}
private
RoslynDefinitionBucket
GetOrCreateDefinitionBucket
(
DefinitionItem
definition
)
public
sealed
override
Task
OnReferenceFoundAsync
(
SourceReferenceItem
reference
)
=>
OnReferenceFoundWorkerAsync
(
reference
);
protected
abstract
Task
OnReferenceFoundWorkerAsync
(
SourceReferenceItem
reference
);
protected
RoslynDefinitionBucket
GetOrCreateDefinitionBucket
(
DefinitionItem
definition
)
{
lock
(
_gate
)
{
...
...
@@ -682,7 +465,7 @@ private RoslynDefinitionBucket GetOrCreateDefinitionBucket(DefinitionItem defini
}
}
public
override
Task
ReportProgressAsync
(
int
current
,
int
maximum
)
public
sealed
override
Task
ReportProgressAsync
(
int
current
,
int
maximum
)
{
// https://devdiv.visualstudio.com/web/wi.aspx?pcguid=011b8bdf-6d56-4f87-be0d-0092136884d9&id=359162
// Right now VS actually responds to each SetProgess call by enqueueing a UI task
...
...
@@ -717,9 +500,9 @@ public ITableEntriesSnapshot GetCurrentSnapshot()
// our version.
if
(
_lastSnapshot
?.
VersionNumber
!=
CurrentVersionNumber
)
{
var
entries
=
_currentlyGroupingByDefinition
&&
!
_alwaysIncludeDeclarations
?
_entriesW
ithoutDeclarations
:
_entriesW
ithDeclarations
;
var
entries
=
_currentlyGroupingByDefinition
?
_entriesW
henGroupingByDefinition
:
_entriesW
henNotGroupingByDefinition
;
_lastSnapshot
=
new
TableEntriesSnapshot
(
entries
,
CurrentVersionNumber
);
}
...
...
@@ -754,7 +537,356 @@ void IDisposable.Dispose()
CancelSearch
();
}
protected
async
Task
<(
Guid
,
SourceText
)>
GetGuidAndSourceTextAsync
(
Document
document
)
{
// The FAR system needs to know the guid for the project that a def/reference is
// from (to support features like filtering). Normally that would mean we could
// only support this from a VisualStudioWorkspace. However, we want till work
// in cases lke Any-Code (which does not use a VSWorkspace). So we are tolerant
// when we have another type of workspace. This means we will show results, but
// certain features (like filtering) may not work in that context.
var
workspace
=
document
.
Project
.
Solution
.
Workspace
as
VisualStudioWorkspaceImpl
;
var
guid
=
workspace
?.
GetHostProject
(
document
.
Project
.
Id
)?.
Guid
??
Guid
.
Empty
;
var
sourceText
=
await
document
.
GetTextAsync
(
CancellationToken
).
ConfigureAwait
(
false
);
return
(
guid
,
sourceText
);
}
#
endregion
}
private
class
WithReferencesFindUsagesContext
:
AbstractTableDataSourceFindUsagesContext
{
public
WithReferencesFindUsagesContext
(
StreamingFindUsagesPresenter
presenter
,
IFindAllReferencesWindow
findReferencesWindow
)
:
base
(
presenter
,
findReferencesWindow
)
{
}
protected
override
async
Task
OnDefinitionFoundWorkerAsync
(
DefinitionItem
definition
)
{
// If this is a definition we always want to show, then create entries
// for all the declaration locations immediately. Otherwise, we'll
// create them on demand when we hear about references for this definition.
if
(
definition
.
DisplayIfNoReferences
)
{
await
AddDeclarationEntriesAsync
(
definition
).
ConfigureAwait
(
false
);
}
}
private
async
Task
AddDeclarationEntriesAsync
(
DefinitionItem
definition
)
{
CancellationToken
.
ThrowIfCancellationRequested
();
// Don't do anything if we already have declaration entries for this definition
// (i.e. another thread beat us to this).
if
(
HasDeclarationEntries
(
definition
))
{
return
;
}
var
definitionBucket
=
GetOrCreateDefinitionBucket
(
definition
);
// We could do this inside the lock. but that would mean async activity in a
// lock, and i'd like to avoid that. That does mean that we might do extra
// work if multiple threads end up down htis path. But only one of them will
// win when we access the lock below.
var
declarations
=
ArrayBuilder
<
Entry
>.
GetInstance
();
foreach
(
var
declarationLocation
in
definition
.
SourceSpans
)
{
var
definitionEntry
=
await
CreateDocumentLocationEntryAsync
(
definitionBucket
,
declarationLocation
,
isDefinitionLocation
:
true
).
ConfigureAwait
(
false
);
if
(
definitionEntry
!=
null
)
{
declarations
.
Add
(
definitionEntry
);
}
}
var
changed
=
false
;
lock
(
_gate
)
{
// Do one final check to ensure that no other thread beat us here.
if
(!
HasDeclarationEntries
(
definition
))
{
// We only include declaration entries in the entries we show when
// not grouping by definition.
_entriesWhenNotGroupingByDefinition
=
_entriesWhenNotGroupingByDefinition
.
AddRange
(
declarations
);
CurrentVersionNumber
++;
changed
=
true
;
}
}
declarations
.
Free
();
if
(
changed
)
{
// Let all our subscriptions know that we've updated.
NotifyChange
();
}
}
private
bool
HasDeclarationEntries
(
DefinitionItem
definition
)
{
lock
(
_gate
)
{
return
_entriesWhenNotGroupingByDefinition
.
Any
(
e
=>
e
.
DefinitionBucket
.
DefinitionItem
==
definition
);
}
}
protected
override
Task
OnReferenceFoundWorkerAsync
(
SourceReferenceItem
reference
)
{
// Normal references go into both sets of entries.
return
OnEntryFoundAsync
(
reference
.
Definition
,
bucket
=>
CreateDocumentLocationEntryAsync
(
bucket
,
reference
.
SourceSpan
,
isDefinitionLocation
:
false
),
addToEntriesWhenGroupingByDefinition
:
true
,
addToEntriesWhenNotGroupingByDefinition
:
true
);
}
protected
async
Task
OnEntryFoundAsync
(
DefinitionItem
definition
,
Func
<
RoslynDefinitionBucket
,
Task
<
Entry
>>
createEntryAsync
,
bool
addToEntriesWhenGroupingByDefinition
,
bool
addToEntriesWhenNotGroupingByDefinition
)
{
Debug
.
Assert
(
addToEntriesWhenGroupingByDefinition
||
addToEntriesWhenNotGroupingByDefinition
);
CancellationToken
.
ThrowIfCancellationRequested
();
// Ok, we got a *reference* to some definition item. This may have been
// a reference for some definition that we haven't created any declaration
// entries for (i.e. becuase it had DisplayIfNoReferences = false). Because
// we've now found a reference, we want to make sure all its declaration
// entries are added.
await
AddDeclarationEntriesAsync
(
definition
).
ConfigureAwait
(
false
);
// First find the bucket corresponding to our definition.
var
definitionBucket
=
GetOrCreateDefinitionBucket
(
definition
);
var
entry
=
await
createEntryAsync
(
definitionBucket
).
ConfigureAwait
(
false
);
lock
(
_gate
)
{
// Once we can make the new entry, add it to the appropriate list.
if
(
addToEntriesWhenGroupingByDefinition
)
{
_entriesWhenGroupingByDefinition
=
_entriesWhenGroupingByDefinition
.
Add
(
entry
);
}
if
(
addToEntriesWhenNotGroupingByDefinition
)
{
_entriesWhenNotGroupingByDefinition
=
_entriesWhenNotGroupingByDefinition
.
Add
(
entry
);
}
CurrentVersionNumber
++;
}
// Let all our subscriptions know that we've updated.
NotifyChange
();
}
protected
override
async
Task
OnCompletedAsyncWorkerAsync
()
{
// Now that we know the search is over, create and display any error messages
// for definitions that were not found.
await
CreateMissingReferenceEntriesIfNecessaryAsync
().
ConfigureAwait
(
false
);
await
CreateNoResultsFoundEntryIfNecessaryAsync
().
ConfigureAwait
(
false
);
}
private
async
Task
CreateMissingReferenceEntriesIfNecessaryAsync
()
{
await
CreateMissingReferenceEntriesIfNecessaryAsync
(
whenGroupingByDefinition
:
true
).
ConfigureAwait
(
false
);
await
CreateMissingReferenceEntriesIfNecessaryAsync
(
whenGroupingByDefinition
:
false
).
ConfigureAwait
(
false
);
}
private
async
Task
CreateMissingReferenceEntriesIfNecessaryAsync
(
bool
whenGroupingByDefinition
)
{
// Go through and add dummy entries for any definitions that
// that we didn't find any references for.
var
definitions
=
GetDefinitionsToCreateMissingReferenceItemsFor
(
whenGroupingByDefinition
);
foreach
(
var
definition
in
definitions
)
{
// Create a fake reference to this definition that says
// "no references found to <symbolname>".
await
OnEntryFoundAsync
(
definition
,
bucket
=>
SimpleMessageEntry
.
CreateAsync
(
bucket
,
GetMessage
(
bucket
.
DefinitionItem
)),
addToEntriesWhenGroupingByDefinition
:
whenGroupingByDefinition
,
addToEntriesWhenNotGroupingByDefinition
:
!
whenGroupingByDefinition
).
ConfigureAwait
(
false
);
}
}
private
static
string
GetMessage
(
DefinitionItem
definition
)
{
if
(
definition
.
IsExternal
)
{
return
ServicesVisualStudioNextResources
.
External_reference_found
;
}
return
string
.
Format
(
ServicesVisualStudioNextResources
.
No_references_found_to_0
,
definition
.
NameDisplayParts
.
JoinText
());
}
private
ImmutableArray
<
DefinitionItem
>
GetDefinitionsToCreateMissingReferenceItemsFor
(
bool
whenGroupingByDefinition
)
{
lock
(
_gate
)
{
var
entries
=
whenGroupingByDefinition
?
_entriesWhenGroupingByDefinition
:
_entriesWhenNotGroupingByDefinition
;
// Find any definitions that we didn't have any references to. But only show
// them if they want to be displayed without any references. This will
// ensure that we still see things like overrides and whatnot, but we
// won't show property-accessors.
var
seenDefinitions
=
entries
.
Select
(
r
=>
r
.
DefinitionBucket
.
DefinitionItem
).
ToSet
();
var
q
=
from
definition
in
_definitions
where
!
seenDefinitions
.
Contains
(
definition
)
&&
definition
.
DisplayIfNoReferences
select
definition
;
// If we find at least one of these types of definitions, then just return those.
var
result
=
ImmutableArray
.
CreateRange
(
q
);
if
(
result
.
Length
>
0
)
{
return
result
;
}
// We found no definitions that *want* to be displayed. However, we still
// want to show something. So, if necessary, show at lest the first definition
// even if we found no references and even if it would prefer to not be seen.
if
(
entries
.
Count
==
0
&&
_definitions
.
Count
>
0
)
{
return
ImmutableArray
.
Create
(
_definitions
.
First
());
}
return
ImmutableArray
<
DefinitionItem
>.
Empty
;
}
}
private
async
Task
CreateNoResultsFoundEntryIfNecessaryAsync
()
{
bool
noDefinitions
;
lock
(
_gate
)
{
noDefinitions
=
this
.
_definitions
.
Count
==
0
;
}
if
(
noDefinitions
)
{
// Create a fake definition/reference called "search found no results"
await
OnEntryFoundAsync
(
NoResultsDefinitionItem
,
bucket
=>
SimpleMessageEntry
.
CreateAsync
(
bucket
,
ServicesVisualStudioNextResources
.
Search_found_no_results
),
addToEntriesWhenGroupingByDefinition
:
true
,
addToEntriesWhenNotGroupingByDefinition
:
true
).
ConfigureAwait
(
false
);
}
}
private
static
readonly
DefinitionItem
NoResultsDefinitionItem
=
DefinitionItem
.
CreateNonNavigableItem
(
GlyphTags
.
GetTags
(
Glyph
.
StatusInformation
),
ImmutableArray
.
Create
(
new
TaggedText
(
TextTags
.
Text
,
ServicesVisualStudioNextResources
.
Search_found_no_results
)));
}
private
class
WithoutReferencesFindUsagesContext
:
AbstractTableDataSourceFindUsagesContext
{
public
WithoutReferencesFindUsagesContext
(
StreamingFindUsagesPresenter
presenter
,
IFindAllReferencesWindow
findReferencesWindow
)
:
base
(
presenter
,
findReferencesWindow
)
{
DisableGroupingByDefinition
();
}
private
void
DisableGroupingByDefinition
()
{
Presenter
.
AssertIsForeground
();
var
newColumns
=
ArrayBuilder
<
ColumnState
>.
GetInstance
();
foreach
(
var
columnState
in
_tableControl
.
ColumnStates
)
{
var
columnState2
=
columnState
as
ColumnState2
;
if
(
columnState
?.
Name
==
StandardTableColumnDefinitions2
.
Definition
)
{
newColumns
.
Add
(
new
ColumnState2
(
columnState2
.
Name
,
isVisible
:
false
,
width
:
columnState2
.
Width
,
sortPriority
:
columnState2
.
SortPriority
,
descendingSort
:
columnState2
.
DescendingSort
,
groupingPriority
:
0
));
}
else
{
newColumns
.
Add
(
columnState
);
}
}
_tableControl
.
SetColumnStates
(
newColumns
);
newColumns
.
Free
();
}
protected
override
Task
OnReferenceFoundWorkerAsync
(
SourceReferenceItem
reference
)
=>
throw
new
InvalidOperationException
();
protected
override
Task
OnCompletedAsyncWorkerAsync
()
=>
SpecializedTasks
.
EmptyTask
;
protected
override
async
Task
OnDefinitionFoundWorkerAsync
(
DefinitionItem
definition
)
{
var
definitionBucket
=
GetOrCreateDefinitionBucket
(
definition
);
var
entries
=
ArrayBuilder
<
Entry
>.
GetInstance
();
try
{
if
(
definition
.
SourceSpans
.
Length
==
1
)
{
var
entry
=
await
CreateEntryAsync
(
definitionBucket
,
definition
).
ConfigureAwait
(
false
);
entries
.
Add
(
entry
);
}
else
{
foreach
(
var
sourceSpan
in
definition
.
SourceSpans
)
{
var
entry
=
await
CreateDocumentLocationEntryAsync
(
definitionBucket
,
sourceSpan
,
isDefinitionLocation
:
true
).
ConfigureAwait
(
false
);
entries
.
Add
(
entry
);
}
}
if
(
entries
.
Count
>
0
)
{
lock
(
_gate
)
{
_entriesWhenGroupingByDefinition
=
_entriesWhenGroupingByDefinition
.
AddRange
(
entries
);
_entriesWhenNotGroupingByDefinition
=
_entriesWhenNotGroupingByDefinition
.
AddRange
(
entries
);
}
this
.
NotifyChange
();
}
}
finally
{
entries
.
Free
();
}
}
private
async
Task
<
Entry
>
CreateEntryAsync
(
RoslynDefinitionBucket
definitionBucket
,
DefinitionItem
definition
)
{
var
documentSpan
=
definition
.
SourceSpans
[
0
];
var
(
guid
,
sourceText
)
=
await
GetGuidAndSourceTextAsync
(
documentSpan
.
Document
).
ConfigureAwait
(
false
);
return
new
DefinitionItemEntry
(
this
,
definitionBucket
,
documentSpan
,
guid
,
sourceText
);
}
}
}
}
\ No newline at end of file
src/VisualStudio/Core/Next/FindReferences/StreamingFindUsagesPresenter.cs
浏览文件 @
799b963c
...
...
@@ -60,7 +60,7 @@ internal partial class StreamingFindUsagesPresenter :
_vsFindAllReferencesService
=
(
IFindAllReferencesService
)
_serviceProvider
.
GetService
(
typeof
(
SVsFindAllReferences
));
}
public
FindUsagesContext
StartSearch
(
string
title
,
bool
alwaysShowDeclaration
s
)
public
FindUsagesContext
StartSearch
(
string
title
,
bool
canShowReference
s
)
{
this
.
AssertIsForeground
();
...
...
@@ -68,8 +68,10 @@ public FindUsagesContext StartSearch(string title, bool alwaysShowDeclarations)
var
window
=
_vsFindAllReferencesService
.
StartSearch
(
title
);
// Make the data source that will feed data into this window.
var
dataSource
=
new
TableDataSourceFindUsagesContext
(
this
,
window
,
alwaysShowDeclarations
);
var
dataSource
=
canShowReferences
?
(
AbstractTableDataSourceFindUsagesContext
)
new
WithReferencesFindUsagesContext
(
this
,
window
)
:
new
WithoutReferencesFindUsagesContext
(
this
,
window
);
// And return the data source so that the FindRefs engine can report results
// which the data source can then create the appropriate presentation items for
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录