Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
ed030c6b
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,发现更多精彩内容 >>
未验证
提交
ed030c6b
编写于
4月 03, 2020
作者:
A
Allison Chou
提交者:
GitHub
4月 03, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #42854 from allisonchou/LSP_FAR
Move Find All References to LSP
上级
1404c540
ecef67a3
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
552 addition
and
293 deletion
+552
-293
src/EditorFeatures/CSharp/FindUsages/CSharpFindUsagesLSPService.cs
...rFeatures/CSharp/FindUsages/CSharpFindUsagesLSPService.cs
+23
-0
src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
...itorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
+14
-2
src/EditorFeatures/Core/FindUsages/IFindUsagesLSPService.cs
src/EditorFeatures/Core/FindUsages/IFindUsagesLSPService.cs
+25
-0
src/EditorFeatures/VisualBasic/FindUsages/VisualBasicFindUsagesLSPService.vb
...VisualBasic/FindUsages/VisualBasicFindUsagesLSPService.vb
+21
-0
src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs
...LanguageServer/Protocol/Extensions/ProtocolConversions.cs
+73
-0
src/Features/LanguageServer/Protocol/Handler/Initialize/InitializeHandler.cs
...geServer/Protocol/Handler/Initialize/InitializeHandler.cs
+1
-0
src/Features/LanguageServer/Protocol/Handler/References/FindAllReferencesHandler.cs
...r/Protocol/Handler/References/FindAllReferencesHandler.cs
+208
-0
src/Features/LanguageServer/Protocol/LanguageServerProtocol.cs
...eatures/LanguageServer/Protocol/LanguageServerProtocol.cs
+25
-13
src/Features/LanguageServer/ProtocolUnitTests/References/FindAllReferencesHandlerTests.cs
...ocolUnitTests/References/FindAllReferencesHandlerTests.cs
+154
-0
src/VisualStudio/Core/Def/Implementation/LanguageClient/InProcLanguageServer.cs
...Def/Implementation/LanguageClient/InProcLanguageServer.cs
+8
-1
src/VisualStudio/LiveShare/Impl/Client/References/RoslynFindUsagesService.cs
...veShare/Impl/Client/References/RoslynFindUsagesService.cs
+0
-73
src/VisualStudio/LiveShare/Impl/Client/RoslynLSPClientService.cs
...ualStudio/LiveShare/Impl/Client/RoslynLSPClientService.cs
+0
-1
src/VisualStudio/LiveShare/Impl/FindAllReferencesHandler.Exports.cs
...Studio/LiveShare/Impl/FindAllReferencesHandler.Exports.cs
+0
-54
src/VisualStudio/LiveShare/Impl/FindAllReferencesHandler.cs
src/VisualStudio/LiveShare/Impl/FindAllReferencesHandler.cs
+0
-149
未找到文件。
src/
VisualStudio/LiveShare/Impl/Client/References/RoslynFindUsagesService.Exports
.cs
→
src/
EditorFeatures/CSharp/FindUsages/CSharpFindUsagesLSPService
.cs
浏览文件 @
ed030c6b
...
...
@@ -5,28 +5,18 @@
using
System
;
using
System.Composition
;
using
Microsoft.CodeAnalysis.Editor.FindUsages
;
using
Microsoft.CodeAnalysis.Editor.Shared.Utilities
;
using
Microsoft.CodeAnalysis.Host.Mef
;
namespace
Microsoft.
VisualStudio.LanguageServices.LiveShare.Client.Referenc
es
namespace
Microsoft.
CodeAnalysis.Editor.CSharp.FindUsag
es
{
[
ExportLanguageService
(
typeof
(
IFindUsages
Service
),
StringConstants
.
CSharpLspLanguageName
),
Shared
]
internal
class
CSharp
LspFindUsagesService
:
Roslyn
FindUsagesService
[
ExportLanguageService
(
typeof
(
IFindUsages
LSPService
),
LanguageNames
.
CSharp
),
Shared
]
internal
class
CSharp
FindUsagesLSPService
:
Abstract
FindUsagesService
{
[
ImportingConstructor
]
[
Obsolete
(
MefConstruction
.
ImportingConstructorMessage
,
error
:
true
)]
public
CSharpLspFindUsagesService
(
CSharpLspClientServiceFactory
csharpLspClientServiceFactory
,
RemoteLanguageServiceWorkspace
remoteLanguageServiceWorkspace
)
:
base
(
csharpLspClientServiceFactory
,
remoteLanguageServiceWorkspace
)
{
}
}
[
ExportLanguageService
(
typeof
(
IFindUsagesService
),
StringConstants
.
VBLspLanguageName
),
Shared
]
internal
class
VBLspFindUsagesService
:
RoslynFindUsagesService
{
[
ImportingConstructor
]
[
Obsolete
(
MefConstruction
.
ImportingConstructorMessage
,
error
:
true
)]
public
VBLspFindUsagesService
(
VisualBasicLspClientServiceFactory
vbLspClientServiceFactory
,
RemoteLanguageServiceWorkspace
remoteLanguageServiceWorkspace
)
:
base
(
vbLspClientServiceFactory
,
remoteLanguageServiceWorkspace
)
public
CSharpFindUsagesLSPService
(
IThreadingContext
threadingContext
)
:
base
(
threadingContext
)
{
}
}
...
...
src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
浏览文件 @
ed030c6b
...
...
@@ -18,7 +18,7 @@
namespace
Microsoft.CodeAnalysis.Editor.FindUsages
{
internal
abstract
partial
class
AbstractFindUsagesService
:
IFindUsagesService
internal
abstract
partial
class
AbstractFindUsagesService
:
IFindUsagesService
,
IFindUsagesLSPService
{
private
readonly
IThreadingContext
_threadingContext
;
...
...
@@ -60,7 +60,7 @@ protected AbstractFindUsagesService(IThreadingContext threadingContext)
}
}
public
async
Task
FindReferencesAsync
(
async
Task
IFindUsagesService
.
FindReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
var
definitionTrackingContext
=
new
DefinitionTrackingContext
(
context
);
...
...
@@ -88,6 +88,18 @@ protected AbstractFindUsagesService(IThreadingContext threadingContext)
}
}
async
Task
IFindUsagesLSPService
.
FindReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
// We don't need to get third party definitions when finding references in LSP.
// Currently, 3rd party definitions = XAML definitions, and XAML will provide
// references via LSP instead of hooking into Roslyn.
// This also means that we don't need to be on the UI thread.
var
definitionTrackingContext
=
new
DefinitionTrackingContext
(
context
);
await
FindLiteralOrSymbolReferencesAsync
(
document
,
position
,
definitionTrackingContext
).
ConfigureAwait
(
false
);
}
private
async
Task
FindLiteralOrSymbolReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
...
...
src/EditorFeatures/Core/FindUsages/IFindUsagesLSPService.cs
0 → 100644
浏览文件 @
ed030c6b
// 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.Threading.Tasks
;
using
Microsoft.CodeAnalysis.FindUsages
;
using
Microsoft.CodeAnalysis.Host
;
namespace
Microsoft.CodeAnalysis.Editor.FindUsages
{
internal
interface
IFindUsagesLSPService
:
ILanguageService
{
/// <summary>
/// Finds the references for the symbol at the specific position in the document,
/// pushing the results into the context instance.
/// </summary>
Task
FindReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
);
/// <summary>
/// Finds the implementations for the symbol at the specific position in the document,
/// pushing the results into the context instance.
/// </summary>
Task
FindImplementationsAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
);
}
}
src/EditorFeatures/VisualBasic/FindUsages/VisualBasicFindUsagesLSPService.vb
0 → 100644
浏览文件 @
ed030c6b
' 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.
Imports
System.Composition
Imports
Microsoft.CodeAnalysis.Editor.FindUsages
Imports
Microsoft.CodeAnalysis.Editor.Shared.Utilities
Imports
Microsoft.CodeAnalysis.Host.Mef
Namespace
Microsoft.CodeAnalysis.Editor.VisualBasic.FindUsages
<
ExportLanguageService
(
GetType
(
IFindUsagesLSPService
),
LanguageNames
.
VisualBasic
),
[
Shared
]
>
Friend
Class
VisualBasicFindUsagesLSPService
Inherits
AbstractFindUsagesService
<
ImportingConstructor
>
<
Obsolete
(
MefConstruction
.
ImportingConstructorMessage
,
True
)
>
Public
Sub
New
(
threadingContext
As
IThreadingContext
)
MyBase
.
New
(
threadingContext
)
End
Sub
End
Class
End
Namespace
src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs
浏览文件 @
ed030c6b
...
...
@@ -12,6 +12,7 @@
using
Microsoft.CodeAnalysis.Tags
;
using
Microsoft.CodeAnalysis.Text
;
using
Microsoft.VisualStudio.Text.Adornments
;
using
Microsoft.VisualStudio.Utilities
;
using
Roslyn.Utilities
;
using
LSP
=
Microsoft
.
VisualStudio
.
LanguageServer
.
Protocol
;
...
...
@@ -381,5 +382,77 @@ public static Glyph CompletionItemKindToGlyph(LSP.CompletionItemKind kind)
return
Glyph
.
None
;
}
}
// The mappings here are roughly based off of SymbolUsageInfoExtensions.ToSymbolReferenceKinds.
public
static
LSP
.
ReferenceKind
[]
SymbolUsageInfoToReferenceKinds
(
SymbolUsageInfo
symbolUsageInfo
)
{
var
referenceKinds
=
ArrayBuilder
<
LSP
.
ReferenceKind
>.
GetInstance
();
if
(
symbolUsageInfo
.
ValueUsageInfoOpt
.
HasValue
)
{
var
usageInfo
=
symbolUsageInfo
.
ValueUsageInfoOpt
.
Value
;
if
(
usageInfo
.
IsReadFrom
())
{
referenceKinds
.
Add
(
LSP
.
ReferenceKind
.
Read
);
}
if
(
usageInfo
.
IsWrittenTo
())
{
referenceKinds
.
Add
(
LSP
.
ReferenceKind
.
Write
);
}
if
(
usageInfo
.
IsReference
())
{
referenceKinds
.
Add
(
LSP
.
ReferenceKind
.
Reference
);
}
if
(
usageInfo
.
IsNameOnly
())
{
referenceKinds
.
Add
(
LSP
.
ReferenceKind
.
Name
);
}
}
if
(
symbolUsageInfo
.
TypeOrNamespaceUsageInfoOpt
.
HasValue
)
{
var
usageInfo
=
symbolUsageInfo
.
TypeOrNamespaceUsageInfoOpt
.
Value
;
if
((
usageInfo
&
TypeOrNamespaceUsageInfo
.
Qualified
)
!=
0
)
{
referenceKinds
.
Add
(
LSP
.
ReferenceKind
.
Qualified
);
}
if
((
usageInfo
&
TypeOrNamespaceUsageInfo
.
TypeArgument
)
!=
0
)
{
referenceKinds
.
Add
(
LSP
.
ReferenceKind
.
TypeArgument
);
}
if
((
usageInfo
&
TypeOrNamespaceUsageInfo
.
TypeConstraint
)
!=
0
)
{
referenceKinds
.
Add
(
LSP
.
ReferenceKind
.
TypeConstraint
);
}
if
((
usageInfo
&
TypeOrNamespaceUsageInfo
.
Base
)
!=
0
)
{
referenceKinds
.
Add
(
LSP
.
ReferenceKind
.
BaseType
);
}
// Preserving the same mapping logic that SymbolUsageInfoExtensions.ToSymbolReferenceKinds uses
if
((
usageInfo
&
TypeOrNamespaceUsageInfo
.
ObjectCreation
)
!=
0
)
{
referenceKinds
.
Add
(
LSP
.
ReferenceKind
.
Constructor
);
}
if
((
usageInfo
&
TypeOrNamespaceUsageInfo
.
Import
)
!=
0
)
{
referenceKinds
.
Add
(
LSP
.
ReferenceKind
.
Import
);
}
// Preserving the same mapping logic that SymbolUsageInfoExtensions.ToSymbolReferenceKinds uses
if
((
usageInfo
&
TypeOrNamespaceUsageInfo
.
NamespaceDeclaration
)
!=
0
)
{
referenceKinds
.
Add
(
LSP
.
ReferenceKind
.
Declaration
);
}
}
return
referenceKinds
.
ToArrayAndFree
();
}
}
}
src/Features/LanguageServer/Protocol/Handler/Initialize/InitializeHandler.cs
浏览文件 @
ed030c6b
...
...
@@ -50,6 +50,7 @@ public Task<LSP.InitializeResult> HandleRequestAsync(Solution solution, LSP.Init
DocumentRangeFormattingProvider
=
true
,
DocumentOnTypeFormattingProvider
=
new
LSP
.
DocumentOnTypeFormattingOptions
{
FirstTriggerCharacter
=
"}"
,
MoreTriggerCharacter
=
new
[]
{
";"
,
"\n"
}
},
DocumentHighlightProvider
=
true
,
ReferencesProvider
=
true
,
}
});
}
...
...
src/Features/LanguageServer/Protocol/Handler/References/FindAllReferencesHandler.cs
0 → 100644
浏览文件 @
ed030c6b
// 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.Generic
;
using
System.Collections.Immutable
;
using
System.Composition
;
using
System.Diagnostics
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis
;
using
Microsoft.CodeAnalysis.Classification
;
using
Microsoft.CodeAnalysis.Editor
;
using
Microsoft.CodeAnalysis.Editor.FindUsages
;
using
Microsoft.CodeAnalysis.Editor.Shared.Utilities
;
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.FindSymbols.Finders
;
using
Microsoft.CodeAnalysis.FindUsages
;
using
Microsoft.CodeAnalysis.Host.Mef
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.VisualStudio.LanguageServer.Protocol
;
using
Microsoft.VisualStudio.Text.Adornments
;
using
Roslyn.Utilities
;
using
LSP
=
Microsoft
.
VisualStudio
.
LanguageServer
.
Protocol
;
namespace
Microsoft.CodeAnalysis.LanguageServer.Handler
{
[
ExportLspMethod
(
LSP
.
Methods
.
TextDocumentReferencesName
),
Shared
]
internal
class
FindAllReferencesHandler
:
IRequestHandler
<
LSP
.
ReferenceParams
,
LSP
.
VSReferenceItem
[
]>
{
private
readonly
IThreadingContext
_threadingContext
;
private
readonly
IMetadataAsSourceFileService
_metadataAsSourceFileService
;
[
ImportingConstructor
]
[
Obsolete
(
MefConstruction
.
ImportingConstructorMessage
,
error
:
true
)]
public
FindAllReferencesHandler
(
IThreadingContext
threadingContext
,
IMetadataAsSourceFileService
metadataAsSourceFileService
)
{
_threadingContext
=
threadingContext
;
_metadataAsSourceFileService
=
metadataAsSourceFileService
;
}
public
async
Task
<
LSP
.
VSReferenceItem
[
]>
HandleRequestAsync
(
Solution
solution
,
ReferenceParams
referenceParams
,
ClientCapabilities
clientCapabilities
,
CancellationToken
cancellationToken
)
{
Debug
.
Assert
(
clientCapabilities
.
HasVisualStudioLspCapability
());
var
document
=
solution
.
GetDocumentFromURI
(
referenceParams
.
TextDocument
.
Uri
);
if
(
document
==
null
)
{
return
Array
.
Empty
<
LSP
.
VSReferenceItem
>();
}
var
findUsagesService
=
document
.
GetRequiredLanguageService
<
IFindUsagesLSPService
>();
var
position
=
await
document
.
GetPositionFromLinePositionAsync
(
ProtocolConversions
.
PositionToLinePosition
(
referenceParams
.
Position
),
cancellationToken
).
ConfigureAwait
(
false
);
var
context
=
new
SimpleFindUsagesContext
(
cancellationToken
);
// Finds the references for the symbol at the specific position in the document, pushing the results to the context instance.
await
findUsagesService
.
FindReferencesAsync
(
document
,
position
,
context
).
ConfigureAwait
(
false
);
return
await
GetReferenceItemsAsync
(
document
,
position
,
context
,
cancellationToken
).
ConfigureAwait
(
false
);
}
private
async
Task
<
LSP
.
VSReferenceItem
[
]>
GetReferenceItemsAsync
(
Document
document
,
int
position
,
SimpleFindUsagesContext
context
,
CancellationToken
cancellationToken
)
{
// Mapping each reference to its definition
var
definitionMap
=
new
Dictionary
<
DefinitionItem
,
List
<
SourceReferenceItem
>>();
foreach
(
var
reference
in
context
.
GetReferences
())
{
if
(!
definitionMap
.
ContainsKey
(
reference
.
Definition
))
{
definitionMap
.
Add
(
reference
.
Definition
,
new
List
<
SourceReferenceItem
>());
}
definitionMap
[
reference
.
Definition
].
Add
(
reference
);
}
// NOTE: Parts of FAR currently do not display correctly due to a bug in LSP.VSReferenceItem.
// https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1088938/
using
var
_
=
ArrayBuilder
<
LSP
.
VSReferenceItem
>.
GetInstance
(
out
var
referenceItems
);
// Each reference is assigned its own unique id
var
id
=
0
;
foreach
(
var
(
definition
,
references
)
in
definitionMap
)
{
// Creating the reference item that corresponds to the definition.
var
definitionItem
=
await
GenerateReferenceItem
(
id
,
definitionId
:
id
,
document
,
position
,
definition
.
SourceSpans
.
FirstOrDefault
(),
context
,
definition
.
DisplayableProperties
,
definition
.
GetClassifiedText
(),
symbolUsageInfo
:
null
,
cancellationToken
).
ConfigureAwait
(
false
);
// If we have an empty location, skip this definition and its references.
if
(
definitionItem
.
Location
==
null
)
{
continue
;
}
referenceItems
.
Add
(
definitionItem
);
var
definitionId
=
id
;
id
++;
// Creating a reference item for each reference.
foreach
(
var
reference
in
references
)
{
var
referenceItem
=
await
GenerateReferenceItem
(
id
,
definitionId
,
document
,
position
,
reference
.
SourceSpan
,
context
,
reference
.
AdditionalProperties
,
definitionText
:
null
,
reference
.
SymbolUsageInfo
,
cancellationToken
).
ConfigureAwait
(
false
);
// If we have an empty location, skip this reference.
if
(
referenceItem
.
Location
==
null
)
{
continue
;
}
referenceItems
.
Add
(
referenceItem
);
id
++;
};
}
return
referenceItems
.
ToArray
();
async
Task
<
LSP
.
VSReferenceItem
>
GenerateReferenceItem
(
int
id
,
int
?
definitionId
,
Document
originalDocument
,
int
originalPosition
,
DocumentSpan
documentSpan
,
SimpleFindUsagesContext
context
,
ImmutableDictionary
<
string
,
string
>
properties
,
ClassifiedTextElement
?
definitionText
,
SymbolUsageInfo
?
symbolUsageInfo
,
CancellationToken
cancellationToken
)
{
LSP
.
Location
?
location
=
null
;
// If we have no source span, our location may be in metadata.
if
(
documentSpan
==
default
)
{
var
symbol
=
await
SymbolFinder
.
FindSymbolAtPositionAsync
(
originalDocument
,
originalPosition
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
symbol
!=
null
&&
symbol
.
Locations
!=
null
&&
!
symbol
.
Locations
.
IsEmpty
&&
symbol
.
Locations
.
First
().
IsInMetadata
)
{
var
declarationFile
=
await
_metadataAsSourceFileService
.
GetGeneratedFileAsync
(
originalDocument
.
Project
,
symbol
,
allowDecompilation
:
false
,
cancellationToken
).
ConfigureAwait
(
false
);
var
linePosSpan
=
declarationFile
.
IdentifierLocation
.
GetLineSpan
().
Span
;
location
=
new
LSP
.
Location
{
Uri
=
new
Uri
(
declarationFile
.
FilePath
),
Range
=
ProtocolConversions
.
LinePositionToRange
(
linePosSpan
),
};
}
}
else
{
location
=
await
ProtocolConversions
.
DocumentSpanToLocationAsync
(
documentSpan
,
cancellationToken
).
ConfigureAwait
(
false
);
}
// TO-DO: The Origin property should be added once Rich-Nav is completed.
// https://github.com/dotnet/roslyn/issues/42847
var
result
=
new
LSP
.
VSReferenceItem
{
ContainingMember
=
properties
.
TryGetValue
(
AbstractReferenceFinder
.
ContainingMemberInfoPropertyName
,
out
var
referenceContainingMember
)
?
referenceContainingMember
:
null
,
ContainingType
=
properties
.
TryGetValue
(
AbstractReferenceFinder
.
ContainingTypeInfoPropertyName
,
out
var
referenceContainingType
)
?
referenceContainingType
:
null
,
DefinitionId
=
definitionId
,
DefinitionText
=
definitionText
,
// Only definitions should have a non-null DefinitionText
DisplayPath
=
location
?.
Uri
.
LocalPath
,
DocumentName
=
documentSpan
==
default
?
null
:
documentSpan
.
Document
.
Name
,
Id
=
id
,
Kind
=
symbolUsageInfo
.
HasValue
?
ProtocolConversions
.
SymbolUsageInfoToReferenceKinds
(
symbolUsageInfo
.
Value
)
:
new
ReferenceKind
[]
{
},
Location
=
location
,
ProjectName
=
documentSpan
==
default
?
null
:
documentSpan
.
Document
.
Project
.
Name
,
ResolutionStatus
=
ResolutionStatusKind
.
ConfirmedAsReference
,
};
// Properly assigning the text property.
if
(
id
==
definitionId
)
{
result
.
Text
=
definitionText
;
}
else
if
(
documentSpan
!=
default
)
{
var
classifiedSpansAndHighlightSpan
=
await
ClassifiedSpansAndHighlightSpanFactory
.
ClassifyAsync
(
documentSpan
,
cancellationToken
).
ConfigureAwait
(
false
);
var
classifiedSpans
=
classifiedSpansAndHighlightSpan
.
ClassifiedSpans
;
var
docText
=
await
documentSpan
.
Document
.
GetTextAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
result
.
Text
=
new
ClassifiedTextElement
(
classifiedSpans
.
Select
(
cspan
=>
new
ClassifiedTextRun
(
cspan
.
ClassificationType
,
docText
.
ToString
(
cspan
.
TextSpan
))));
}
return
result
;
}
}
}
}
src/Features/LanguageServer/Protocol/LanguageServerProtocol.cs
浏览文件 @
ed030c6b
...
...
@@ -153,6 +153,18 @@ public Task<LSP.TextEdit[]> FormatDocumentRangeAsync(Solution solution, LSP.Docu
public
Task
<
LSP
.
DocumentHighlight
[
]>
GetDocumentHighlightAsync
(
Solution
solution
,
LSP
.
TextDocumentPositionParams
request
,
LSP
.
ClientCapabilities
clientCapabilities
,
CancellationToken
cancellationToken
)
=>
ExecuteRequestAsync
<
LSP
.
TextDocumentPositionParams
,
LSP
.
DocumentHighlight
[
]>
(
LSP
.
Methods
.
TextDocumentDocumentHighlightName
,
solution
,
request
,
clientCapabilities
,
cancellationToken
);
/// <summary>
/// Answers a document references request by returning references information associated with the symbol at a given document location.
/// https://microsoft.github.io/language-server-protocol/specification#textDocument_references
/// </summary>
/// <param name="solution">the solution containing the request document.</param>
/// <param name="request">the references request.</param>
/// <param name="clientCapabilities">the client capabilities for the request.</param>
/// <param name="cancellationToken">a cancellation token.</param>
/// <returns>references information associated with the symbol at the given document location.</returns>
public
Task
<
LSP
.
VSReferenceItem
[
]>
GetDocumentReferencesAsync
(
Solution
solution
,
LSP
.
ReferenceParams
request
,
LSP
.
ClientCapabilities
clientCapabilities
,
CancellationToken
cancellationToken
)
=>
ExecuteRequestAsync
<
LSP
.
ReferenceParams
,
LSP
.
VSReferenceItem
[
]>
(
LSP
.
Methods
.
TextDocumentReferencesName
,
solution
,
request
,
clientCapabilities
,
cancellationToken
);
/// <summary>
/// Answers a document symbols request by returning a list of symbols in the document.
/// https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol
...
...
@@ -182,7 +194,7 @@ public Task<LSP.FoldingRange[]> GetFoldingRangeAsync(Solution solution, LSP.Fold
/// https://microsoft.github.io/language-server-protocol/specification#textDocument_hover
/// </summary>
/// <param name="solution">the solution containing any documents in the request.</param>
/// <param name="request">the hover reques
s
t.</param>
/// <param name="request">the hover request.</param>
/// <param name="clientCapabilities">the client capabilities for the request.</param>
/// <param name="cancellationToken">a cancellation token.</param>
/// <returns>the Hover using MarkupContent.</returns>
...
...
@@ -225,18 +237,6 @@ public Task<LSP.SymbolInformation[]> GetWorkspaceSymbolsAsync(Solution solution,
public
Task
<
LSP
.
SumType
<
LSP
.
Location
,
LSP
.
Location
[
]>
?>
GoToDefinitionAsync
(
Solution
solution
,
LSP
.
TextDocumentPositionParams
request
,
LSP
.
ClientCapabilities
clientCapabilities
,
CancellationToken
cancellationToken
)
=>
ExecuteRequestAsync
<
LSP
.
TextDocumentPositionParams
,
LSP
.
SumType
<
LSP
.
Location
,
LSP
.
Location
[
]>
?>(
LSP
.
Methods
.
TextDocumentDefinitionName
,
solution
,
request
,
clientCapabilities
,
cancellationToken
);
/// <summary>
/// Answers a rename request by returning the workspace edit for a given symbol.
/// https://microsoft.github.io/language-server-protocol/specification#textDocument_rename
/// </summary>
/// <param name="solution">the solution containing the request.</param>
/// <param name="request">the document position of the symbol to rename.</param>
/// <param name="clientCapabilities">the client capabilities for the request.</param>
/// <param name="cancellationToken">a cancellation token.</param>
/// <returns>the workspace edits to rename the given symbol</returns>
public
Task
<
WorkspaceEdit
>
RenameAsync
(
Solution
solution
,
LSP
.
RenameParams
request
,
LSP
.
ClientCapabilities
clientCapabilities
,
CancellationToken
cancellationToken
)
=>
ExecuteRequestAsync
<
LSP
.
RenameParams
,
WorkspaceEdit
>(
LSP
.
Methods
.
TextDocumentRenameName
,
solution
,
request
,
clientCapabilities
,
cancellationToken
);
/// <summary>
/// Answers a goto type definition request by returning the location of a given type definition.
/// https://microsoft.github.io/language-server-protocol/specification#textDocument_typeDefinition
...
...
@@ -261,6 +261,18 @@ public Task<LSP.Location[]> GoToTypeDefinitionAsync(Solution solution, LSP.TextD
public
Task
<
LSP
.
InitializeResult
>
InitializeAsync
(
Solution
solution
,
LSP
.
InitializeParams
request
,
LSP
.
ClientCapabilities
clientCapabilities
,
CancellationToken
cancellationToken
)
=>
ExecuteRequestAsync
<
LSP
.
InitializeParams
,
LSP
.
InitializeResult
>(
LSP
.
Methods
.
InitializeName
,
solution
,
request
,
clientCapabilities
,
cancellationToken
);
/// <summary>
/// Answers a rename request by returning the workspace edit for a given symbol.
/// https://microsoft.github.io/language-server-protocol/specification#textDocument_rename
/// </summary>
/// <param name="solution">the solution containing the request.</param>
/// <param name="request">the document position of the symbol to rename.</param>
/// <param name="clientCapabilities">the client capabilities for the request.</param>
/// <param name="cancellationToken">a cancellation token.</param>
/// <returns>the workspace edits to rename the given symbol</returns>
public
Task
<
WorkspaceEdit
>
RenameAsync
(
Solution
solution
,
LSP
.
RenameParams
request
,
LSP
.
ClientCapabilities
clientCapabilities
,
CancellationToken
cancellationToken
)
=>
ExecuteRequestAsync
<
LSP
.
RenameParams
,
WorkspaceEdit
>(
LSP
.
Methods
.
TextDocumentRenameName
,
solution
,
request
,
clientCapabilities
,
cancellationToken
);
/// <summary>
/// Answers a request to resolve a completion item.
/// https://microsoft.github.io/language-server-protocol/specification#completionItem_resolve
...
...
src/
VisualStudio/LiveShare/Test
/FindAllReferencesHandlerTests.cs
→
src/
Features/LanguageServer/ProtocolUnitTests/References
/FindAllReferencesHandlerTests.cs
浏览文件 @
ed030c6b
...
...
@@ -3,17 +3,15 @@
// See the LICENSE file in the project root for more information.
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis
;
using
Microsoft.VisualStudio.LanguageServer.Protocol
;
using
Newtonsoft.Json.Linq
;
using
Roslyn.Test.Utilities
;
using
Xunit
;
using
LSP
=
Microsoft
.
VisualStudio
.
LanguageServer
.
Protocol
;
namespace
Microsoft.
VisualStudio.LanguageServices.LiveShare.UnitTest
s
namespace
Microsoft.
CodeAnalysis.LanguageServer.UnitTests.Reference
s
{
public
class
FindAllReferencesHandlerTests
:
AbstractL
iveShareRequestHandler
Tests
public
class
FindAllReferencesHandlerTests
:
AbstractL
anguageServerProtocol
Tests
{
[
WpfFact
]
public
async
Task
TestFindAllReferencesAsync
()
...
...
@@ -37,34 +35,15 @@ void M2()
}"
;
using
var
workspace
=
CreateTestWorkspace
(
markup
,
out
var
locations
);
var
results
=
await
RunFindAllReferencesAsync
(
workspace
.
CurrentSolution
,
locations
[
"caret"
].
First
(),
true
);
AssertLocationsEqual
(
locations
[
"reference"
],
results
);
}
var
results
=
await
RunFindAllReferencesAsync
(
workspace
.
CurrentSolution
,
locations
[
"caret"
].
First
());
AssertLocationsEqual
(
locations
[
"reference"
],
results
.
Select
(
result
=>
result
.
Location
));
[
WpfFact
]
public
async
Task
TestFindAllReferencesAsync_DoNotIncludeDeclarations
()
{
var
markup
=
@"class A
{
public int someInt = 1;
void M()
{
var i = {|reference:someInt|} + 1;
}
}
class B
{
int someInt = A.{|reference:someInt|} + 1;
void M2()
{
var j = someInt + A.{|caret:|}{|reference:someInt|};
}
}"
;
using
var
workspace
=
CreateTestWorkspace
(
markup
,
out
var
locations
);
Assert
.
Equal
(
"A"
,
results
[
0
].
ContainingType
);
Assert
.
Equal
(
"B"
,
results
[
2
].
ContainingType
);
Assert
.
Equal
(
"M"
,
results
[
1
].
ContainingMember
);
Assert
.
Equal
(
"M2"
,
results
[
3
].
ContainingMember
);
var
results
=
await
RunFindAllReferencesAsync
(
workspace
.
CurrentSolution
,
locations
[
"caret"
].
First
(),
false
);
AssertLocationsEqual
(
locations
[
"reference"
],
results
);
AssertValidDefinitionProperties
(
results
,
0
);
}
[
WpfFact
]
...
...
@@ -91,8 +70,15 @@ void M2()
using
var
workspace
=
CreateTestWorkspace
(
markups
,
out
var
locations
);
var
results
=
await
RunFindAllReferencesAsync
(
workspace
.
CurrentSolution
,
locations
[
"caret"
].
First
(),
true
);
AssertLocationsEqual
(
locations
[
"reference"
],
results
);
var
results
=
await
RunFindAllReferencesAsync
(
workspace
.
CurrentSolution
,
locations
[
"caret"
].
First
());
AssertLocationsEqual
(
locations
[
"reference"
],
results
.
Select
(
result
=>
result
.
Location
));
Assert
.
Equal
(
"A"
,
results
[
0
].
ContainingType
);
Assert
.
Equal
(
"B"
,
results
[
2
].
ContainingType
);
Assert
.
Equal
(
"M"
,
results
[
1
].
ContainingMember
);
Assert
.
Equal
(
"M2"
,
results
[
3
].
ContainingMember
);
AssertValidDefinitionProperties
(
results
,
0
);
}
[
WpfFact
]
...
...
@@ -105,24 +91,64 @@ public async Task TestFindAllReferencesAsync_InvalidLocation()
}"
;
using
var
workspace
=
CreateTestWorkspace
(
markup
,
out
var
locations
);
var
results
=
await
RunFindAllReferencesAsync
(
workspace
.
CurrentSolution
,
locations
[
"caret"
].
First
()
,
true
);
var
results
=
await
RunFindAllReferencesAsync
(
workspace
.
CurrentSolution
,
locations
[
"caret"
].
First
());
Assert
.
Empty
(
results
);
}
private
static
async
Task
<
LSP
.
Location
[
]>
RunFindAllReferencesAsync
(
Solution
solution
,
LSP
.
Location
caret
,
bool
includeDeclaration
)
[
WpfFact
]
public
async
Task
TestFindAllReferencesMetadataDefinitionAsync
()
{
var
request
=
(
JObject
)
JToken
.
FromObject
(
new
LSP
.
ReferenceParams
()
var
markup
=
@"using System;
class A
{
void M()
{
Console.{|caret:|}{|reference:WriteLine|}(""text"");
}
}"
;
using
var
workspace
=
CreateTestWorkspace
(
markup
,
out
var
locations
);
var
results
=
await
RunFindAllReferencesAsync
(
workspace
.
CurrentSolution
,
locations
[
"caret"
].
First
());
Assert
.
NotNull
(
results
[
0
].
Location
.
Uri
);
}
private
static
LSP
.
ReferenceParams
CreateReferenceParams
(
LSP
.
Location
caret
)
=>
new
LSP
.
ReferenceParams
()
{
TextDocument
=
CreateTextDocumentIdentifier
(
caret
.
Uri
),
Position
=
caret
.
Range
.
Start
,
Context
=
new
LSP
.
ReferenceContext
()
Context
=
new
LSP
.
ReferenceContext
(),
};
private
static
async
Task
<
LSP
.
VSReferenceItem
[
]>
RunFindAllReferencesAsync
(
Solution
solution
,
LSP
.
Location
caret
)
{
var
vsClientCapabilities
=
new
LSP
.
VSClientCapabilities
{
SupportsVisualStudioExtensions
=
true
};
return
await
GetLanguageServer
(
solution
).
GetDocumentReferencesAsync
(
solution
,
CreateReferenceParams
(
caret
),
vsClientCapabilities
,
CancellationToken
.
None
);
}
private
static
void
AssertValidDefinitionProperties
(
LSP
.
ReferenceItem
[]
referenceItems
,
int
definitionIndex
)
{
var
definition
=
referenceItems
[
definitionIndex
];
var
definitionId
=
definition
.
DefinitionId
;
Assert
.
NotNull
(
definition
.
DefinitionText
);
for
(
var
i
=
0
;
i
<
referenceItems
.
Length
;
i
++)
{
if
(
i
==
definitionIndex
)
{
IncludeDeclaration
=
includeDeclaration
continue
;
}
});
var
references
=
await
TestHandleAsync
<
object
,
object
[
]>
(
solution
,
request
,
Methods
.
TextDocumentReferencesName
);
return
references
.
Select
(
o
=>
(
LSP
.
Location
)
o
).
ToArray
();
Assert
.
Null
(
referenceItems
[
i
].
DefinitionText
);
Assert
.
Equal
(
definitionId
,
referenceItems
[
i
].
DefinitionId
);
Assert
.
NotEqual
(
definitionId
,
referenceItems
[
i
].
Id
);
}
}
}
}
src/VisualStudio/Core/Def/Implementation/LanguageClient/InProcLanguageServer.cs
浏览文件 @
ed030c6b
...
...
@@ -126,10 +126,17 @@ public void Exit()
[
JsonRpcMethod
(
Methods
.
TextDocumentRenameName
)]
public
Task
<
WorkspaceEdit
>
GetTextDocumentRenameAsync
(
JToken
input
,
CancellationToken
cancellationToken
)
{
var
renameParams
=
input
.
ToObject
<
RenameParams
>();
var
renameParams
=
input
.
ToObject
<
RenameParams
>(
JsonSerializer
);
return
_protocol
.
RenameAsync
(
_workspace
.
CurrentSolution
,
renameParams
,
_clientCapabilities
,
cancellationToken
);
}
[
JsonRpcMethod
(
Methods
.
TextDocumentReferencesName
)]
public
Task
<
VSReferenceItem
[
]>
GetTextDocumentReferencesAsync
(
JToken
input
,
CancellationToken
cancellationToken
)
{
var
referencesParams
=
input
.
ToObject
<
ReferenceParams
>(
JsonSerializer
);
return
_protocol
.
GetDocumentReferencesAsync
(
_workspace
.
CurrentSolution
,
referencesParams
,
_clientCapabilities
,
cancellationToken
);
}
[
JsonRpcMethod
(
Methods
.
TextDocumentCompletionName
)]
public
Task
<
SumType
<
CompletionItem
[],
CompletionList
>?>
GetTextDocumentCompletionAsync
(
JToken
input
,
CancellationToken
cancellationToken
)
{
...
...
src/VisualStudio/LiveShare/Impl/Client/References/RoslynFindUsagesService.cs
已删除
100644 → 0
浏览文件 @
1404c540
// 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.Threading.Tasks
;
using
Microsoft.CodeAnalysis
;
using
Microsoft.CodeAnalysis.Editor.FindUsages
;
using
Microsoft.CodeAnalysis.FindUsages
;
using
Microsoft.CodeAnalysis.LanguageServer
;
using
Microsoft.VisualStudio.LanguageServices.LiveShare.Protocol
;
using
LSP
=
Microsoft
.
VisualStudio
.
LanguageServer
.
Protocol
;
namespace
Microsoft.VisualStudio.LanguageServices.LiveShare.Client.References
{
internal
class
RoslynFindUsagesService
:
IFindUsagesService
{
private
readonly
AbstractLspClientServiceFactory
_roslynLspClientServiceFactory
;
private
readonly
RemoteLanguageServiceWorkspace
_remoteLanguageServiceWorkspace
;
public
RoslynFindUsagesService
(
AbstractLspClientServiceFactory
roslynLspClientServiceFactory
,
RemoteLanguageServiceWorkspace
remoteLanguageServiceWorkspace
)
{
_roslynLspClientServiceFactory
=
roslynLspClientServiceFactory
??
throw
new
ArgumentNullException
(
nameof
(
roslynLspClientServiceFactory
));
_remoteLanguageServiceWorkspace
=
remoteLanguageServiceWorkspace
??
throw
new
ArgumentNullException
(
nameof
(
remoteLanguageServiceWorkspace
));
}
public
Task
FindImplementationsAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
// Find implementations is now handled by the VS LSP client.
return
Task
.
CompletedTask
;
}
public
async
Task
FindReferencesAsync
(
Document
document
,
int
position
,
IFindUsagesContext
context
)
{
var
text
=
await
document
.
GetTextAsync
().
ConfigureAwait
(
false
);
var
lspClient
=
_roslynLspClientServiceFactory
.
ActiveLanguageServerClient
;
if
(
lspClient
==
null
)
{
return
;
}
var
referenceParams
=
new
LSP
.
ReferenceParams
{
Context
=
new
LSP
.
ReferenceContext
{
IncludeDeclaration
=
false
},
TextDocument
=
ProtocolConversions
.
DocumentToTextDocumentIdentifier
(
document
),
Position
=
ProtocolConversions
.
LinePositionToPosition
(
text
.
Lines
.
GetLinePosition
(
position
))
};
var
locations
=
await
lspClient
.
RequestAsync
(
LSP
.
Methods
.
TextDocumentReferences
.
ToLSRequest
(),
referenceParams
,
context
.
CancellationToken
).
ConfigureAwait
(
false
);
if
(
locations
==
null
)
{
return
;
}
// TODO: Need to get real definition data from the server.
var
dummyDef
=
DefinitionItem
.
CreateNonNavigableItem
(
ImmutableArray
<
string
>.
Empty
,
ImmutableArray
<
TaggedText
>.
Empty
);
await
context
.
OnDefinitionFoundAsync
(
dummyDef
).
ConfigureAwait
(
false
);
foreach
(
var
location
in
locations
)
{
var
documentSpan
=
await
_remoteLanguageServiceWorkspace
.
GetDocumentSpanFromLocationAsync
(
location
,
context
.
CancellationToken
).
ConfigureAwait
(
false
);
if
(
documentSpan
==
null
)
{
continue
;
}
await
context
.
OnReferenceFoundAsync
(
new
SourceReferenceItem
(
dummyDef
,
documentSpan
.
Value
)).
ConfigureAwait
(
false
);
}
}
}
}
src/VisualStudio/LiveShare/Impl/Client/RoslynLSPClientService.cs
浏览文件 @
ed030c6b
...
...
@@ -97,7 +97,6 @@ public Task<ICollaborationService> CreateServiceAsync(CollaborationSession colla
// Uses Roslyn client.
CodeActionProvider
=
true
,
ExecuteCommandProvider
=
new
ExecuteCommandOptions
(),
ReferencesProvider
=
true
,
})));
var
lifeTimeService
=
LspClientLifeTimeService
;
...
...
src/VisualStudio/LiveShare/Impl/FindAllReferencesHandler.Exports.cs
已删除
100644 → 0
浏览文件 @
1404c540
// 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.ComponentModel.Composition
;
using
Microsoft.CodeAnalysis.Editor.Shared.Utilities
;
using
Microsoft.CodeAnalysis.Host.Mef
;
using
Microsoft.VisualStudio.LanguageServer.Protocol
;
using
Microsoft.VisualStudio.LiveShare.LanguageServices
;
namespace
Microsoft.VisualStudio.LanguageServices.LiveShare
{
[
ExportLspRequestHandler
(
LiveShareConstants
.
RoslynContractName
,
Methods
.
TextDocumentReferencesName
)]
[
Obsolete
(
"Used for backwards compatibility with old liveshare clients."
)]
internal
class
RoslynFindAllReferencesHandler
:
FindAllReferencesHandler
{
[
ImportingConstructor
]
[
Obsolete
(
MefConstruction
.
ImportingConstructorMessage
,
error
:
true
)]
public
RoslynFindAllReferencesHandler
(
IThreadingContext
threadingContext
)
:
base
(
threadingContext
)
{
}
}
[
ExportLspRequestHandler
(
LiveShareConstants
.
CSharpContractName
,
Methods
.
TextDocumentReferencesName
)]
internal
class
CSharpFindAllReferencesHandler
:
FindAllReferencesHandler
{
[
ImportingConstructor
]
[
Obsolete
(
MefConstruction
.
ImportingConstructorMessage
,
error
:
true
)]
public
CSharpFindAllReferencesHandler
(
IThreadingContext
threadingContext
)
:
base
(
threadingContext
)
{
}
}
[
ExportLspRequestHandler
(
LiveShareConstants
.
VisualBasicContractName
,
Methods
.
TextDocumentReferencesName
)]
internal
class
VisualBasicFindAllReferencesHandler
:
FindAllReferencesHandler
{
[
ImportingConstructor
]
[
Obsolete
(
MefConstruction
.
ImportingConstructorMessage
,
error
:
true
)]
public
VisualBasicFindAllReferencesHandler
(
IThreadingContext
threadingContext
)
:
base
(
threadingContext
)
{
}
}
[
ExportLspRequestHandler
(
LiveShareConstants
.
TypeScriptContractName
,
Methods
.
TextDocumentReferencesName
)]
internal
class
TypeScriptFindAllReferencesHandler
:
FindAllReferencesHandler
{
[
ImportingConstructor
]
[
Obsolete
(
MefConstruction
.
ImportingConstructorMessage
,
error
:
true
)]
public
TypeScriptFindAllReferencesHandler
(
IThreadingContext
threadingContext
)
:
base
(
threadingContext
)
{
}
}
}
src/VisualStudio/LiveShare/Impl/FindAllReferencesHandler.cs
已删除
100644 → 0
浏览文件 @
1404c540
// 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.Generic
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis
;
using
Microsoft.CodeAnalysis.Classification
;
using
Microsoft.CodeAnalysis.Editor.FindUsages
;
using
Microsoft.CodeAnalysis.Editor.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Editor.Shared.Utilities
;
using
Microsoft.CodeAnalysis.FindUsages
;
using
Microsoft.CodeAnalysis.LanguageServer
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.VisualStudio.LanguageServer.Protocol
;
using
Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService
;
using
Microsoft.VisualStudio.LiveShare.LanguageServices
;
using
Microsoft.VisualStudio.Shell
;
using
Microsoft.VisualStudio.Text.Adornments
;
using
Newtonsoft.Json.Linq
;
using
LSP
=
Microsoft
.
VisualStudio
.
LanguageServer
.
Protocol
;
namespace
Microsoft.VisualStudio.LanguageServices.LiveShare
{
// TODO - This should move to the ILanguageClient when we remove the UI thread dependency.
// https://github.com/dotnet/roslyn/issues/38477
// The VS LSP client supports streaming using IProgress<T> on various requests.
// However, this is not yet supported through Live Share, so deserialization fails on the IProgress<T> property.
// https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1043376 tracks Live Share support for this (committed for 16.6).
internal
class
FindAllReferencesHandler
:
ILspRequestHandler
<
object
,
object
[],
Solution
>
{
private
readonly
IThreadingContext
_threadingContext
;
public
FindAllReferencesHandler
(
IThreadingContext
threadingContext
)
=>
_threadingContext
=
threadingContext
;
// TODO - When FAR moves to ILanguageClient, we should switch from using ReferenceGroup (now obsolete) to ReferenceItem.
// https://github.com/dotnet/roslyn/issues/42581
[
System
.
Obsolete
]
public
async
Task
<
object
[
]>
HandleAsync
(
object
request
,
RequestContext
<
Solution
>
requestContext
,
CancellationToken
cancellationToken
)
{
// The VS LSP client supports streaming using IProgress<T> on various requests.
// However, this is not yet supported through Live Share, so deserialization fails on the IProgress<T> property.
// https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1043376 tracks Live Share support for this (committed for 16.6).
var
referenceParams
=
((
JObject
)
request
).
ToObject
<
ReferenceParams
>(
InProcLanguageServer
.
JsonSerializer
);
var
locations
=
ArrayBuilder
<
LSP
.
Location
>.
GetInstance
();
var
solution
=
requestContext
.
Context
;
var
document
=
solution
.
GetDocumentFromURI
(
referenceParams
.
TextDocument
.
Uri
);
if
(
document
==
null
)
{
return
locations
.
ToArrayAndFree
();
}
var
findUsagesService
=
document
.
Project
.
LanguageServices
.
GetService
<
IFindUsagesService
>();
var
position
=
await
document
.
GetPositionFromLinePositionAsync
(
ProtocolConversions
.
PositionToLinePosition
(
referenceParams
.
Position
),
cancellationToken
).
ConfigureAwait
(
false
);
var
context
=
new
SimpleFindUsagesContext
(
cancellationToken
);
// Roslyn calls into third party extensions to compute reference results and needs to be on the UI thread to compute results.
// This is not great for us and ideally we should ask for a Roslyn API where we can make this call without blocking the UI.
if
(
VsTaskLibraryHelper
.
ServiceInstance
!=
null
)
{
await
_threadingContext
.
JoinableTaskFactory
.
SwitchToMainThreadAsync
(
cancellationToken
);
}
await
findUsagesService
.
FindReferencesAsync
(
document
,
position
,
context
).
ConfigureAwait
(
false
);
if
(
requestContext
?.
ClientCapabilities
?.
ToObject
<
VSClientCapabilities
>()?.
HasVisualStudioLspCapability
()
==
true
)
{
return
await
GetReferenceGroupsAsync
(
referenceParams
,
context
,
cancellationToken
).
ConfigureAwait
(
false
);
}
else
{
return
await
GetLocationsAsync
(
referenceParams
,
context
,
cancellationToken
).
ConfigureAwait
(
false
);
}
}
[
System
.
Obsolete
]
private
async
Task
<
LSP
.
ReferenceGroup
[
]>
GetReferenceGroupsAsync
(
LSP
.
ReferenceParams
request
,
SimpleFindUsagesContext
context
,
CancellationToken
cancellationToken
)
{
var
definitionMap
=
new
Dictionary
<
DefinitionItem
,
List
<
SourceReferenceItem
>>();
foreach
(
var
reference
in
context
.
GetReferences
())
{
if
(!
definitionMap
.
ContainsKey
(
reference
.
Definition
))
{
definitionMap
.
Add
(
reference
.
Definition
,
new
List
<
SourceReferenceItem
>());
}
definitionMap
[
reference
.
Definition
].
Add
(
reference
);
}
var
referenceGroups
=
ArrayBuilder
<
LSP
.
ReferenceGroup
>.
GetInstance
();
foreach
(
var
keyValuePair
in
definitionMap
)
{
var
definition
=
keyValuePair
.
Key
;
var
references
=
keyValuePair
.
Value
;
var
referenceGroup
=
new
LSP
.
ReferenceGroup
();
var
text
=
definition
.
GetClassifiedText
();
referenceGroup
.
Definition
=
await
ProtocolConversions
.
DocumentSpanToLocationWithTextAsync
(
definition
.
SourceSpans
.
First
(),
text
,
cancellationToken
).
ConfigureAwait
(
false
);
referenceGroup
.
DefinitionIcon
=
new
ImageElement
(
definition
.
Tags
.
GetFirstGlyph
().
GetImageId
());
var
locationWithTexts
=
new
ArrayBuilder
<
LSP
.
LocationWithText
>();
foreach
(
var
reference
in
references
)
{
var
classifiedSpansAndHighlightSpan
=
await
ClassifiedSpansAndHighlightSpanFactory
.
ClassifyAsync
(
reference
.
SourceSpan
,
context
.
CancellationToken
).
ConfigureAwait
(
false
);
var
classifiedSpans
=
classifiedSpansAndHighlightSpan
.
ClassifiedSpans
;
var
referenceLocation
=
await
ProtocolConversions
.
DocumentSpanToLocationAsync
(
reference
.
SourceSpan
,
cancellationToken
).
ConfigureAwait
(
false
);
var
docText
=
await
reference
.
SourceSpan
.
Document
.
GetTextAsync
(
context
.
CancellationToken
).
ConfigureAwait
(
false
);
var
classifiedText
=
new
ClassifiedTextElement
(
classifiedSpans
.
Select
(
cspan
=>
new
ClassifiedTextRun
(
cspan
.
ClassificationType
,
docText
.
ToString
(
cspan
.
TextSpan
))));
var
locationWithText
=
new
LSP
.
LocationWithText
{
Range
=
referenceLocation
.
Range
,
Uri
=
referenceLocation
.
Uri
,
Text
=
classifiedText
};
locationWithTexts
.
Add
(
locationWithText
);
}
referenceGroup
.
References
=
locationWithTexts
.
ToArrayAndFree
();
referenceGroups
.
Add
(
referenceGroup
);
}
return
referenceGroups
.
ToArrayAndFree
();
}
private
static
async
Task
<
LSP
.
Location
[
]>
GetLocationsAsync
(
LSP
.
ReferenceParams
request
,
SimpleFindUsagesContext
context
,
CancellationToken
cancellationToken
)
{
var
locations
=
ArrayBuilder
<
LSP
.
Location
>.
GetInstance
();
if
(
request
.
Context
.
IncludeDeclaration
)
{
foreach
(
var
definition
in
context
.
GetDefinitions
())
{
foreach
(
var
docSpan
in
definition
.
SourceSpans
)
{
locations
.
Add
(
await
ProtocolConversions
.
DocumentSpanToLocationAsync
(
docSpan
,
cancellationToken
).
ConfigureAwait
(
false
));
}
}
}
foreach
(
var
reference
in
context
.
GetReferences
())
{
locations
.
Add
(
await
ProtocolConversions
.
DocumentSpanToLocationAsync
(
reference
.
SourceSpan
,
cancellationToken
).
ConfigureAwait
(
false
));
}
return
locations
.
ToArrayAndFree
();
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录