Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
4a475f6e
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,发现更多精彩内容 >>
提交
4a475f6e
编写于
3月 03, 2015
作者:
B
Brett Forsgren
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
show conditional element access sig-help after arbitrary expressions
the old model would only appear after an identifier name
上级
8f393ba5
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
134 addition
and
12 deletion
+134
-12
src/EditorFeatures/CSharp/SignatureHelp/ElementAccessExpressionSignatureHelpProvider.cs
...atureHelp/ElementAccessExpressionSignatureHelpProvider.cs
+79
-12
src/EditorFeatures/CSharpTest/SignatureHelp/ElementAccessExpressionSignatureHelpProviderTests.cs
...Help/ElementAccessExpressionSignatureHelpProviderTests.cs
+14
-0
src/EditorFeatures/VisualBasicTest/SignatureHelp/InvocationExpressionSignatureHelpProviderTests.vb
...ureHelp/InvocationExpressionSignatureHelpProviderTests.vb
+41
-0
未找到文件。
src/EditorFeatures/CSharp/SignatureHelp/ElementAccessExpressionSignatureHelpProvider.cs
浏览文件 @
4a475f6e
...
...
@@ -39,7 +39,8 @@ public override bool IsRetriggerCharacter(char ch)
private
static
bool
TryGetElementAccessExpression
(
SyntaxNode
root
,
int
position
,
ISyntaxFactsService
syntaxFacts
,
SignatureHelpTriggerReason
triggerReason
,
CancellationToken
cancellationToken
,
out
ExpressionSyntax
identifier
,
out
SyntaxToken
openBrace
)
{
return
CompleteElementAccessExpression
.
TryGetSyntax
(
root
,
position
,
syntaxFacts
,
triggerReason
,
cancellationToken
,
out
identifier
,
out
openBrace
)
||
IncompleteElementAccessExpression
.
TryGetSyntax
(
root
,
position
,
syntaxFacts
,
triggerReason
,
cancellationToken
,
out
identifier
,
out
openBrace
);
IncompleteElementAccessExpression
.
TryGetSyntax
(
root
,
position
,
syntaxFacts
,
triggerReason
,
cancellationToken
,
out
identifier
,
out
openBrace
)
||
ConditionalAccessExpression
.
TryGetSyntax
(
root
,
position
,
syntaxFacts
,
triggerReason
,
cancellationToken
,
out
identifier
,
out
openBrace
);
}
protected
override
async
Task
<
SignatureHelpItems
>
GetItemsWorkerAsync
(
Document
document
,
int
position
,
SignatureHelpTriggerInfo
triggerInfo
,
CancellationToken
cancellationToken
)
...
...
@@ -115,7 +116,15 @@ private TextSpan GetTextSpan(ExpressionSyntax expression, SyntaxToken openBracke
{
if
(
openBracket
.
Parent
is
BracketedArgumentListSyntax
)
{
return
CompleteElementAccessExpression
.
GetTextSpan
(
expression
,
openBracket
);
var
conditional
=
expression
.
Parent
as
ConditionalAccessExpressionSyntax
;
if
(
conditional
!=
null
)
{
return
TextSpan
.
FromBounds
(
conditional
.
Span
.
Start
,
openBracket
.
FullSpan
.
End
);
}
else
{
return
CompleteElementAccessExpression
.
GetTextSpan
(
expression
,
openBracket
);
}
}
else
if
(
openBracket
.
Parent
is
ArrayRankSpecifierSyntax
)
{
...
...
@@ -142,16 +151,35 @@ public override SignatureHelpState GetCurrentArgumentState(SyntaxNode root, int
return
null
;
}
ElementAccessExpressionSyntax
elementAccessExpression
=
SyntaxFactory
.
ElementAccessExpression
(
expression
,
SyntaxFactory
.
ParseBracketedArgumentList
(
openBracket
.
Parent
.
ToString
()));
// If the user is actively typing, it's likely that we're in a broken state and the
// syntax tree will be incorrect. Because of this we need to synthesize a new
// bracketed argument list so we can correctly map the cursor to the current argument
// and then we need to account for this and offset the position check accordingly.
int
offset
;
BracketedArgumentListSyntax
argumentList
;
var
newBracketedArgumentList
=
SyntaxFactory
.
ParseBracketedArgumentList
(
openBracket
.
Parent
.
ToString
());
if
(
expression
.
Parent
is
ConditionalAccessExpressionSyntax
)
{
// The typed code looks like: <expression>?[
var
conditional
=
(
ConditionalAccessExpressionSyntax
)
expression
.
Parent
;
var
elementBinding
=
SyntaxFactory
.
ElementBindingExpression
(
newBracketedArgumentList
);
var
conditionalAccessExpression
=
SyntaxFactory
.
ConditionalAccessExpression
(
expression
,
elementBinding
);
offset
=
expression
.
SpanStart
-
conditionalAccessExpression
.
SpanStart
;
argumentList
=
((
ElementBindingExpressionSyntax
)
conditionalAccessExpression
.
WhenNotNull
).
ArgumentList
;
}
else
{
// The typed code looks like:
// <expression>[
// or
// <identifier>?[
ElementAccessExpressionSyntax
elementAccessExpression
=
SyntaxFactory
.
ElementAccessExpression
(
expression
,
newBracketedArgumentList
);
offset
=
expression
.
SpanStart
-
elementAccessExpression
.
SpanStart
;
argumentList
=
elementAccessExpression
.
ArgumentList
;
}
// Because we synthesized the elementAccessExpression, it will have an index starting at 0
// instead of at the actual position it's at in the text. Because of this, we need to
// offset the position we are checking accordingly.
var
offset
=
expression
.
SpanStart
-
elementAccessExpression
.
SpanStart
;
position
-=
offset
;
return
SignatureHelpUtilities
.
GetSignatureHelpState
(
elementAccessExpression
.
A
rgumentList
,
position
);
return
SignatureHelpUtilities
.
GetSignatureHelpState
(
a
rgumentList
,
position
);
}
private
bool
TryGetComIndexers
(
SemanticModel
semanticModel
,
ExpressionSyntax
expression
,
CancellationToken
cancellationToken
,
out
IEnumerable
<
IPropertySymbol
>
indexers
,
out
ITypeSymbol
expressionType
)
...
...
@@ -254,7 +282,8 @@ internal static bool IsArgumentListToken(ElementAccessExpressionSyntax expressio
internal
static
TextSpan
GetTextSpan
(
SyntaxNode
expression
,
SyntaxToken
openBracket
)
{
Contract
.
ThrowIfFalse
(
openBracket
.
Parent
is
BracketedArgumentListSyntax
&&
openBracket
.
Parent
.
Parent
is
ElementAccessExpressionSyntax
);
Contract
.
ThrowIfFalse
(
openBracket
.
Parent
is
BracketedArgumentListSyntax
&&
(
openBracket
.
Parent
.
Parent
is
ElementAccessExpressionSyntax
||
openBracket
.
Parent
.
Parent
is
ElementBindingExpressionSyntax
));
return
SignatureHelpUtilities
.
GetSignatureHelpSpan
((
BracketedArgumentListSyntax
)
openBracket
.
Parent
);
}
...
...
@@ -275,7 +304,7 @@ internal static bool TryGetSyntax(SyntaxNode root, int position, ISyntaxFactsSer
}
/// Error tolerance case for
/// "foo[]"
/// "foo[
$$]" or "foo?[$$
]"
/// which is parsed as an ArrayTypeSyntax variable declaration instead of an ElementAccessExpression
private
static
class
IncompleteElementAccessExpression
{
...
...
@@ -314,5 +343,43 @@ internal static bool TryGetSyntax(SyntaxNode root, int position, ISyntaxFactsSer
return
false
;
}
}
/// Error tolerance case for
/// "new String()?[$$]"
/// which is parsed as a BracketedArgumentListSyntax parented by an ElementBindingExpressionSyntax parented by a ConditionalAccessExpressionSyntax
private
static
class
ConditionalAccessExpression
{
internal
static
bool
IsTriggerToken
(
SyntaxToken
token
)
{
return
!
token
.
IsKind
(
SyntaxKind
.
None
)
&&
token
.
ValueText
.
Length
==
1
&&
IsTriggerCharacterInternal
(
token
.
ValueText
[
0
])
&&
token
.
Parent
is
BracketedArgumentListSyntax
&&
token
.
Parent
.
Parent
is
ElementBindingExpressionSyntax
&&
token
.
Parent
.
Parent
.
Parent
is
ConditionalAccessExpressionSyntax
;
}
internal
static
bool
IsArgumentListToken
(
ElementBindingExpressionSyntax
expression
,
SyntaxToken
token
)
{
return
expression
.
ArgumentList
.
Span
.
Contains
(
token
.
SpanStart
)
&&
token
!=
expression
.
ArgumentList
.
CloseBracketToken
;
}
internal
static
bool
TryGetSyntax
(
SyntaxNode
root
,
int
position
,
ISyntaxFactsService
syntaxFacts
,
SignatureHelpTriggerReason
triggerReason
,
CancellationToken
cancellationToken
,
out
ExpressionSyntax
identifier
,
out
SyntaxToken
openBrace
)
{
ElementBindingExpressionSyntax
elementBindingExpression
;
if
(
CommonSignatureHelpUtilities
.
TryGetSyntax
(
root
,
position
,
syntaxFacts
,
triggerReason
,
IsTriggerToken
,
IsArgumentListToken
,
cancellationToken
,
out
elementBindingExpression
))
{
identifier
=
((
ConditionalAccessExpressionSyntax
)
elementBindingExpression
.
Parent
).
Expression
;
openBrace
=
elementBindingExpression
.
ArgumentList
.
OpenBracketToken
;
return
true
;
}
identifier
=
null
;
openBrace
=
default
(
SyntaxToken
);
return
false
;
}
}
}
}
src/EditorFeatures/CSharpTest/SignatureHelp/ElementAccessExpressionSignatureHelpProviderTests.cs
浏览文件 @
4a475f6e
...
...
@@ -810,6 +810,20 @@ public void foo()
Test
(
markup
,
expectedOrderedItems
);
}
[
WorkItem
(
32
,
"https://github.com/dotnet/roslyn/issues/32"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
SignatureHelp
)]
public
void
NonIdentifierConditionalIndexer
()
{
var
expected
=
new
[]
{
new
SignatureHelpTestItem
(
"char string[int index]"
)
};
Test
(
@"class C { void M() { """"?[$$ } }"
,
expected
);
// inline with a string literal
Test
(
@"class C { void M() { """"?[/**/$$ } }"
,
expected
);
// inline with a string literal and multiline comment
Test
(
@"class C { void M() { ("""")?[$$ } }"
,
expected
);
// parenthesized expression
Test
(
@"class C { void M() { new System.String(' ', 1)?[$$ } }"
,
expected
);
// new object expression
// more complicated parenthesized expression
Test
(
@"class C { void M() { (null as System.Collections.Generic.List<int>)?[$$ } }"
,
new
[]
{
new
SignatureHelpTestItem
(
"int System.Collections.Generic.List<int>[int index]"
)
});
}
[
WorkItem
(
1067933
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
SignatureHelp
)]
public
void
InvokedWithNoToken
()
...
...
src/EditorFeatures/VisualBasicTest/SignatureHelp/InvocationExpressionSignatureHelpProviderTests.vb
浏览文件 @
4a475f6e
...
...
@@ -932,6 +932,47 @@ End Class
Test
(
markup
,
expected
,
experimental
:
=
True
)
End
Sub
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
SignatureHelp
)
>
Public
Sub
NonIdentifierConditionalIndexer
()
Dim
expected
=
{
New
SignatureHelpTestItem
(
"String(index As Integer) As Char"
)}
' inline with a string literal
Test
(
"
Class C
Sub M()
Dim c =
""""
?($$
End Sub
End Class
"
,
expected
)
' parenthesized expression
Test
(
"
Class C
Sub M()
Dim c = (
""""
)?($$
End Sub
End Class
"
,
expected
)
' new object expression
Test
(
"
Class C
Sub M()
Dim c = (New System.String(
""
""
c, 1))?($$
End Sub
End Class
"
,
expected
)
' more complicated parenthesized expression
Test
(
"
Class C
Sub M()
Dim c = (CType(Nothing, System.Collections.Generic.List(Of Integer)))?($$
End Sub
End Class
"
,
{
New
SignatureHelpTestItem
(
"System.Collections.Generic.List(Of Integer)(index As Integer) As Integer"
)})
End
Sub
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
SignatureHelp
)
>
Public
Sub
TestTriggerCharacters
()
Dim
expectedTriggerCharacters
()
As
Char
=
{
","
c
,
"("
c
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录