Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
a8ee63e8
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,发现更多精彩内容 >>
未验证
提交
a8ee63e8
编写于
8月 07, 2020
作者:
D
David
提交者:
GitHub
8月 07, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #46576 from dibarbet/colorize_hover
Add temporary support for colorization in LSP hover
上级
72c413fd
d872f03f
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
78 addition
and
50 deletion
+78
-50
src/EditorFeatures/CSharpTest/QuickInfo/SyntacticQuickInfoSourceTests.cs
...res/CSharpTest/QuickInfo/SyntacticQuickInfoSourceTests.cs
+2
-4
src/EditorFeatures/Core/Implementation/IntelliSense/Helpers.cs
...ditorFeatures/Core/Implementation/IntelliSense/Helpers.cs
+5
-3
src/EditorFeatures/Core/Implementation/IntelliSense/QuickInfo/IntellisenseQuickInfoBuilder.cs
...on/IntelliSense/QuickInfo/IntellisenseQuickInfoBuilder.cs
+28
-6
src/EditorFeatures/Core/Implementation/IntelliSense/QuickInfo/QuickInfoSourceProvider.QuickInfoSource.cs
...ense/QuickInfo/QuickInfoSourceProvider.QuickInfoSource.cs
+1
-1
src/EditorFeatures/Test2/IntelliSense/AbstractIntellisenseQuickInfoBuilderTests.vb
...IntelliSense/AbstractIntellisenseQuickInfoBuilderTests.vb
+2
-2
src/EditorFeatures/TestUtilities/QuickInfo/AbstractQuickInfoSourceTests.cs
...s/TestUtilities/QuickInfo/AbstractQuickInfoSourceTests.cs
+0
-1
src/Features/LanguageServer/Protocol/Handler/Hover/HoverHandler.cs
...res/LanguageServer/Protocol/Handler/Hover/HoverHandler.cs
+8
-12
src/Features/LanguageServer/ProtocolUnitTests/Hover/HoverTests.cs
...ures/LanguageServer/ProtocolUnitTests/Hover/HoverTests.cs
+32
-21
未找到文件。
src/EditorFeatures/CSharpTest/QuickInfo/SyntacticQuickInfoSourceTests.cs
浏览文件 @
a8ee63e8
...
...
@@ -276,7 +276,6 @@ private static QuickInfoProvider CreateProvider()
protected
override
async
Task
AssertContentIsAsync
(
TestWorkspace
workspace
,
Document
document
,
ITextSnapshot
snapshot
,
int
position
,
string
expectedContent
,
string
expectedDocumentationComment
=
null
)
...
...
@@ -289,7 +288,7 @@ private static QuickInfoProvider CreateProvider()
var
trackingSpan
=
new
Mock
<
ITrackingSpan
>(
MockBehavior
.
Strict
);
var
threadingContext
=
workspace
.
ExportProvider
.
GetExportedValue
<
IThreadingContext
>();
var
streamingPresenter
=
workspace
.
ExportProvider
.
GetExport
<
IStreamingFindUsagesPresenter
>();
var
quickInfoItem
=
await
IntellisenseQuickInfoBuilder
.
BuildItemAsync
(
trackingSpan
.
Object
,
info
,
snapshot
,
document
,
threadingContext
,
streamingPresenter
,
CancellationToken
.
None
);
var
quickInfoItem
=
await
IntellisenseQuickInfoBuilder
.
BuildItemAsync
(
trackingSpan
.
Object
,
info
,
document
,
threadingContext
,
streamingPresenter
,
CancellationToken
.
None
);
var
containerElement
=
quickInfoItem
.
Item
as
ContainerElement
;
var
textElements
=
containerElement
.
Elements
.
OfType
<
ClassifiedTextElement
>();
...
...
@@ -327,7 +326,6 @@ protected override Task TestInScriptAsync(string code, string expectedContent, s
var
testDocument
=
workspace
.
Documents
.
Single
();
var
position
=
testDocument
.
CursorPosition
.
Value
;
var
document
=
workspace
.
CurrentSolution
.
Projects
.
First
().
Documents
.
First
();
var
snapshot
=
testDocument
.
GetTextBuffer
().
CurrentSnapshot
;
if
(
string
.
IsNullOrEmpty
(
expectedContent
))
{
...
...
@@ -335,7 +333,7 @@ protected override Task TestInScriptAsync(string code, string expectedContent, s
}
else
{
await
AssertContentIsAsync
(
workspace
,
document
,
snapshot
,
position
,
expectedContent
,
expectedDocumentationComment
);
await
AssertContentIsAsync
(
workspace
,
document
,
position
,
expectedContent
,
expectedDocumentationComment
);
}
}
}
...
...
src/EditorFeatures/Core/Implementation/IntelliSense/Helpers.cs
浏览文件 @
a8ee63e8
...
...
@@ -2,6 +2,8 @@
// 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
;
...
...
@@ -33,8 +35,8 @@ internal static class Helpers
ImmutableArray
<
TaggedText
>
taggedTexts
,
ref
int
index
,
Document
document
,
IThreadingContext
threadingContext
,
Lazy
<
IStreamingFindUsagesPresenter
>
streamingPresenter
)
IThreadingContext
?
threadingContext
,
Lazy
<
IStreamingFindUsagesPresenter
>
?
streamingPresenter
)
{
// This method produces a sequence of zero or more paragraphs
var
paragraphs
=
new
List
<
object
>();
...
...
@@ -127,7 +129,7 @@ internal static class Helpers
{
// This is tagged text getting added to the current line we are building.
var
style
=
GetClassifiedTextRunStyle
(
part
.
Style
);
if
(
part
.
NavigationTarget
is
object
)
if
(
part
.
NavigationTarget
is
object
&&
streamingPresenter
!=
null
&&
threadingContext
!=
null
)
{
if
(
Uri
.
TryCreate
(
part
.
NavigationTarget
,
UriKind
.
Absolute
,
out
var
absoluteUri
))
{
...
...
src/EditorFeatures/Core/Implementation/IntelliSense/QuickInfo/IntellisenseQuickInfoBuilder.cs
浏览文件 @
a8ee63e8
...
...
@@ -14,7 +14,6 @@
using
Microsoft.CodeAnalysis.Editor.Shared.Utilities
;
using
Microsoft.CodeAnalysis.Formatting
;
using
Microsoft.CodeAnalysis.QuickInfo
;
using
Microsoft.CodeAnalysis.Text.Shared.Extensions
;
using
Microsoft.VisualStudio.Text
;
using
Microsoft.VisualStudio.Text.Adornments
;
...
...
@@ -25,9 +24,7 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo
{
internal
static
class
IntellisenseQuickInfoBuilder
{
internal
static
async
Task
<
IntellisenseQuickInfoItem
>
BuildItemAsync
(
ITrackingSpan
trackingSpan
,
CodeAnalysisQuickInfoItem
quickInfoItem
,
ITextSnapshot
snapshot
,
private
static
async
Task
<
ContainerElement
>
BuildInteractiveContentAsync
(
CodeAnalysisQuickInfoItem
quickInfoItem
,
Document
document
,
IThreadingContext
threadingContext
,
Lazy
<
IStreamingFindUsagesPresenter
>
streamingPresenter
,
...
...
@@ -114,7 +111,7 @@ internal static class IntellisenseQuickInfoBuilder
var
tabSize
=
document
.
Project
.
Solution
.
Workspace
.
Options
.
GetOption
(
FormattingOptions
.
TabSize
,
document
.
Project
.
Language
);
var
text
=
await
document
.
GetTextAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
spans
=
IndentationHelper
.
GetSpansWithAlignedIndentation
(
text
,
classifiedSpanList
.
ToImmutableArray
(),
tabSize
);
var
textRuns
=
spans
.
Select
(
s
=>
new
ClassifiedTextRun
(
s
.
ClassificationType
,
snapshot
.
GetText
(
s
.
TextSpan
.
ToSpan
()
),
ClassifiedTextRunStyle
.
UseClassificationFont
));
var
textRuns
=
spans
.
Select
(
s
=>
new
ClassifiedTextRun
(
s
.
ClassificationType
,
text
.
GetSubText
(
s
.
TextSpan
).
ToString
(
),
ClassifiedTextRunStyle
.
UseClassificationFont
));
if
(
textRuns
.
Any
())
{
...
...
@@ -122,11 +119,36 @@ internal static class IntellisenseQuickInfoBuilder
}
}
var
content
=
new
ContainerElement
(
return
new
ContainerElement
(
ContainerElementStyle
.
Stacked
|
ContainerElementStyle
.
VerticalPadding
,
elements
);
}
internal
static
async
Task
<
IntellisenseQuickInfoItem
>
BuildItemAsync
(
ITrackingSpan
trackingSpan
,
CodeAnalysisQuickInfoItem
quickInfoItem
,
Document
document
,
IThreadingContext
threadingContext
,
Lazy
<
IStreamingFindUsagesPresenter
>
streamingPresenter
,
CancellationToken
cancellationToken
)
{
var
content
=
await
BuildInteractiveContentAsync
(
quickInfoItem
,
document
,
threadingContext
,
streamingPresenter
,
cancellationToken
).
ConfigureAwait
(
false
);
return
new
IntellisenseQuickInfoItem
(
trackingSpan
,
content
);
}
/// <summary>
/// Builds the classified hover content without navigation actions and requiring
/// an instance of <see cref="IStreamingFindUsagesPresenter"/>
/// TODO - This can be removed once LSP supports colorization in markupcontent
/// https://devdiv.visualstudio.com/DevDiv/_workitems/edit/918138
/// </summary>
internal
static
Task
<
ContainerElement
>
BuildContentWithoutNavigationActionsAsync
(
CodeAnalysisQuickInfoItem
quickInfoItem
,
Document
document
,
CancellationToken
cancellationToken
)
{
return
BuildInteractiveContentAsync
(
quickInfoItem
,
document
,
threadingContext
:
null
,
streamingPresenter
:
null
,
cancellationToken
);
}
}
}
src/EditorFeatures/Core/Implementation/IntelliSense/QuickInfo/QuickInfoSourceProvider.QuickInfoSource.cs
浏览文件 @
a8ee63e8
...
...
@@ -70,7 +70,7 @@ public async Task<IntellisenseQuickInfoItem> GetQuickInfoItemAsync(IAsyncQuickIn
{
var
textVersion
=
snapshot
.
Version
;
var
trackingSpan
=
textVersion
.
CreateTrackingSpan
(
item
.
Span
.
ToSpan
(),
SpanTrackingMode
.
EdgeInclusive
);
return
await
IntellisenseQuickInfoBuilder
.
BuildItemAsync
(
trackingSpan
,
item
,
snapshot
,
document
,
_threadingContext
,
_streamingPresenter
,
cancellationToken
).
ConfigureAwait
(
false
);
return
await
IntellisenseQuickInfoBuilder
.
BuildItemAsync
(
trackingSpan
,
item
,
document
,
_threadingContext
,
_streamingPresenter
,
cancellationToken
).
ConfigureAwait
(
false
);
}
return
null
;
...
...
src/EditorFeatures/Test2/IntelliSense/AbstractIntellisenseQuickInfoBuilderTests.vb
浏览文件 @
a8ee63e8
...
...
@@ -44,7 +44,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
Dim
threadingContext
=
workspace
.
ExportProvider
.
GetExportedValue
(
Of
IThreadingContext
)()
Dim
streamingPresenter
=
workspace
.
ExportProvider
.
GetExport
(
Of
IStreamingFindUsagesPresenter
)()
Return
Await
IntellisenseQuickInfoBuilder
.
BuildItemAsync
(
trackingSpan
.
Object
,
quickInfoItem
,
cursorBuffer
.
CurrentSnapshot
,
document
,
threadingContext
,
streamingPresenter
,
CancellationToken
.
None
)
Return
Await
IntellisenseQuickInfoBuilder
.
BuildItemAsync
(
trackingSpan
.
Object
,
quickInfoItem
,
document
,
threadingContext
,
streamingPresenter
,
CancellationToken
.
None
)
End
Using
End
Function
...
...
@@ -68,7 +68,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
Dim
threadingContext
=
workspace
.
ExportProvider
.
GetExportedValue
(
Of
IThreadingContext
)()
Dim
streamingPresenter
=
workspace
.
ExportProvider
.
GetExport
(
Of
IStreamingFindUsagesPresenter
)()
Return
Await
IntellisenseQuickInfoBuilder
.
BuildItemAsync
(
trackingSpan
.
Object
,
codeAnalysisQuickInfoItem
,
cursorBuffer
.
CurrentSnapshot
,
document
,
threadingContext
,
streamingPresenter
,
CancellationToken
.
None
)
Return
Await
IntellisenseQuickInfoBuilder
.
BuildItemAsync
(
trackingSpan
.
Object
,
codeAnalysisQuickInfoItem
,
document
,
threadingContext
,
streamingPresenter
,
CancellationToken
.
None
)
End
Using
End
Function
End
Class
...
...
src/EditorFeatures/TestUtilities/QuickInfo/AbstractQuickInfoSourceTests.cs
浏览文件 @
a8ee63e8
...
...
@@ -51,7 +51,6 @@ protected async Task TestInMethodAndScriptAsync(string code, string expectedCont
protected
abstract
Task
AssertContentIsAsync
(
TestWorkspace
workspace
,
Document
document
,
ITextSnapshot
snapshot
,
int
position
,
string
expectedContent
,
string
expectedDocumentationComment
=
null
);
...
...
src/Features/LanguageServer/Protocol/Handler/Hover/HoverHandler.cs
浏览文件 @
a8ee63e8
...
...
@@ -9,6 +9,7 @@
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo
;
using
Microsoft.CodeAnalysis.Host.Mef
;
using
Microsoft.CodeAnalysis.QuickInfo
;
using
Microsoft.VisualStudio.LanguageServer.Protocol
;
...
...
@@ -43,21 +44,16 @@ public HoverHandler(ILspSolutionProvider solutionProvider) : base(solutionProvid
}
var
text
=
await
document
.
GetTextAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
return
new
Hover
// TODO - Switch to markup content once it supports classifications.
// https://devdiv.visualstudio.com/DevDiv/_workitems/edit/918138
return
new
VSHover
{
Range
=
ProtocolConversions
.
TextSpanToRange
(
info
.
Span
,
text
),
Contents
=
new
MarkupContent
{
Kind
=
MarkupKind
.
Markdown
,
Value
=
GetMarkdownString
(
info
)
}
Contents
=
new
SumType
<
SumType
<
string
,
MarkedString
>,
SumType
<
string
,
MarkedString
>[],
MarkupContent
>(
string
.
Empty
),
// Build the classified text without navigation actions - they are not serializable.
RawContent
=
await
IntellisenseQuickInfoBuilder
.
BuildContentWithoutNavigationActionsAsync
(
info
,
document
,
cancellationToken
).
ConfigureAwait
(
false
)
};
// local functions
// TODO - This should return correctly formatted markdown from quick info.
// https://github.com/dotnet/roslyn/issues/43387
static
string
GetMarkdownString
(
QuickInfoItem
info
)
=>
string
.
Join
(
"\r\n"
,
info
.
Sections
.
Select
(
section
=>
section
.
Text
).
Where
(
text
=>
!
string
.
IsNullOrEmpty
(
text
)));
}
}
}
src/Features/LanguageServer/ProtocolUnitTests/Hover/HoverTests.cs
浏览文件 @
a8ee63e8
...
...
@@ -5,6 +5,8 @@
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.VisualStudio.Text.Adornments
;
using
Roslyn.Test.Utilities
;
using
Xunit
;
using
LSP
=
Microsoft
.
VisualStudio
.
LanguageServer
.
Protocol
;
...
...
@@ -31,10 +33,9 @@ public async Task TestGetHoverAsync()
using
var
workspace
=
CreateTestWorkspace
(
markup
,
out
var
locations
);
var
expectedLocation
=
locations
[
"caret"
].
Single
();
var
expected
=
CreateHover
(
expectedLocation
,
$"string A.Method(int i)\r\n A great method\r\n\r\n
{
FeaturesResources
.
Returns_colon
}
\r\n a string"
);
var
results
=
await
RunGetHoverAsync
(
workspace
.
CurrentSolution
,
expectedLocation
).
ConfigureAwait
(
false
);
AssertJsonEquals
(
expected
,
results
);
VerifyContent
(
results
,
$"string A.Method(int i)|A great method|
{
FeaturesResources
.
Returns_colon
}
| |a string"
);
}
[
Fact
]
...
...
@@ -55,10 +56,9 @@ public async Task TestGetHoverAsync_WithExceptions()
}"
;
using
var
workspace
=
CreateTestWorkspace
(
markup
,
out
var
locations
);
var
expectedLocation
=
locations
[
"caret"
].
Single
();
var
expected
=
CreateHover
(
expectedLocation
,
$"string A.Method(int i)\r\n A great method\r\n\r\n
{
FeaturesResources
.
Exceptions_colon
}
\r\n System.NullReferenceException"
);
var
results
=
await
RunGetHoverAsync
(
workspace
.
CurrentSolution
,
expectedLocation
).
ConfigureAwait
(
false
);
AssertJsonEquals
(
expected
,
results
);
VerifyContent
(
results
,
$"string A.Method(int i)|A great method|
{
FeaturesResources
.
Exceptions_colon
}
| System.NullReferenceException"
);
}
[
Fact
]
...
...
@@ -79,10 +79,9 @@ public async Task TestGetHoverAsync_WithRemarks()
}"
;
using
var
workspace
=
CreateTestWorkspace
(
markup
,
out
var
locations
);
var
expectedLocation
=
locations
[
"caret"
].
Single
();
var
expected
=
CreateHover
(
expectedLocation
,
"string A.Method(int i)\r\n A great method\r\n\r\nRemarks are cool too."
);
var
results
=
await
RunGetHoverAsync
(
workspace
.
CurrentSolution
,
expectedLocation
).
ConfigureAwait
(
false
);
AssertJsonEquals
(
expected
,
results
);
VerifyContent
(
results
,
"string A.Method(int i)|A great method|Remarks are cool too."
);
}
[
Fact
]
...
...
@@ -108,10 +107,9 @@ public async Task TestGetHoverAsync_WithList()
}"
;
using
var
workspace
=
CreateTestWorkspace
(
markup
,
out
var
locations
);
var
expectedLocation
=
locations
[
"caret"
].
Single
();
var
expected
=
CreateHover
(
expectedLocation
,
"string A.Method(int i)\r\n A great method\r\n\r\n• Item 1.\r\n• Item 2."
);
var
results
=
await
RunGetHoverAsync
(
workspace
.
CurrentSolution
,
expectedLocation
).
ConfigureAwait
(
false
);
AssertJsonEquals
(
expected
,
results
);
VerifyContent
(
results
,
"string A.Method(int i)|A great method|• |Item 1.|• |Item 2."
);
}
[
Fact
]
...
...
@@ -187,24 +185,37 @@ static void Main(string[] args)
var
result
=
await
RunGetHoverAsync
(
workspace
.
CurrentSolution
,
location
,
project
.
Id
);
var
expectedConstant
=
project
.
Name
==
"Net472"
?
"Target in net472"
:
"Target in netcoreapp3.1"
;
var
expectedHover
=
CreateHover
(
location
,
$"(
{
FeaturesResources
.
constant
}
) string WithConstant.Target = \"
{
expectedConstant
}
\""
);
AssertJsonEquals
(
expectedHover
,
result
);
VerifyContent
(
result
,
$"(
{
FeaturesResources
.
constant
}
) string WithConstant.Target = \"
{
expectedConstant
}
\""
);
}
}
private
static
async
Task
<
LSP
.
Hover
>
RunGetHoverAsync
(
Solution
solution
,
LSP
.
Location
caret
,
ProjectId
projectContext
=
null
)
=>
await
GetLanguageServer
(
solution
).
ExecuteRequestAsync
<
LSP
.
TextDocumentPositionParams
,
LSP
.
Hover
>(
LSP
.
Methods
.
TextDocumentHoverName
,
private
static
async
Task
<
LSP
.
VS
Hover
>
RunGetHoverAsync
(
Solution
solution
,
LSP
.
Location
caret
,
ProjectId
projectContext
=
null
)
=>
(
LSP
.
VSHover
)
await
GetLanguageServer
(
solution
).
ExecuteRequestAsync
<
LSP
.
TextDocumentPositionParams
,
LSP
.
Hover
>(
LSP
.
Methods
.
TextDocumentHoverName
,
CreateTextDocumentPositionParams
(
caret
,
projectContext
),
new
LSP
.
ClientCapabilities
(),
null
,
CancellationToken
.
None
);
private
static
LSP
.
Hover
CreateHover
(
LSP
.
Location
location
,
string
text
)
=>
new
LSP
.
Hover
()
private
void
VerifyContent
(
LSP
.
VSHover
result
,
string
expectedContent
)
{
var
containerElement
=
(
ContainerElement
)
result
.
RawContent
;
using
var
_
=
ArrayBuilder
<
ClassifiedTextElement
>.
GetInstance
(
out
var
classifiedTextElements
);
GetClassifiedTextElements
(
containerElement
,
classifiedTextElements
);
Assert
.
False
(
classifiedTextElements
.
SelectMany
(
classifiedTextElements
=>
classifiedTextElements
.
Runs
).
Any
(
run
=>
run
.
NavigationAction
!=
null
));
var
content
=
string
.
Join
(
"|"
,
classifiedTextElements
.
Select
(
cte
=>
string
.
Join
(
string
.
Empty
,
cte
.
Runs
.
Select
(
ctr
=>
ctr
.
Text
))));
Assert
.
Equal
(
expectedContent
,
content
);
}
private
void
GetClassifiedTextElements
(
ContainerElement
container
,
ArrayBuilder
<
ClassifiedTextElement
>
classifiedTextElements
)
{
foreach
(
var
element
in
container
.
Elements
)
{
Contents
=
new
LSP
.
MarkupContent
()
if
(
element
is
ClassifiedTextElement
classifiedTextElement
)
{
classifiedTextElements
.
Add
(
classifiedTextElement
);
}
else
if
(
element
is
ContainerElement
containerElement
)
{
Kind
=
LSP
.
MarkupKind
.
Markdown
,
Value
=
text
},
Range
=
location
.
Range
};
GetClassifiedTextElements
(
containerElement
,
classifiedTextElements
);
}
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录