Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
e31a0c4f
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,发现更多精彩内容 >>
提交
e31a0c4f
编写于
4月 21, 2020
作者:
A
Allison Chou
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Code review feedback
上级
283bd9f2
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
147 addition
and
39 deletion
+147
-39
src/EditorFeatures/CSharpTest2/Recommendations/AndKeywordRecommenderTests.cs
...CSharpTest2/Recommendations/AndKeywordRecommenderTests.cs
+51
-0
src/EditorFeatures/CSharpTest2/Recommendations/OrKeywordRecommenderTests.cs
.../CSharpTest2/Recommendations/OrKeywordRecommenderTests.cs
+51
-0
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SyntaxTokenExtensions.cs
...sions/Compiler/CSharp/Extensions/SyntaxTokenExtensions.cs
+1
-1
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/SyntaxTreeExtensions.cs
...ce/CSharp/Extensions/ContextQuery/SyntaxTreeExtensions.cs
+44
-38
未找到文件。
src/EditorFeatures/CSharpTest2/Recommendations/AndKeywordRecommenderTests.cs
浏览文件 @
e31a0c4f
...
...
@@ -126,6 +126,23 @@ void M()
if (e is C2.P $$"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
KeywordRecommending
)]
public
async
Task
TestAfterQualifiedName2
()
{
await
VerifyKeywordAsync
(
@"
namespace N
{
class C
{
const int P = 1;
void M()
{
var e = new object();
if (e is N.C.P $$"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
KeywordRecommending
)]
public
async
Task
TestAtBeginningOfSwitchExpression
()
{
...
...
@@ -180,6 +197,40 @@ public async Task TestAtBeginningOfSwitchStatement_AfterMultipleOpenParens()
case (((1 $$"
));
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
KeywordRecommending
)]
public
async
Task
TestAtBeginningOfSwitchStatement_AfterMultipleOpenParens_MemberAccessExpression
()
{
await
VerifyKeywordAsync
(
@"namespace N
{
class C
{
const int P = 1;
void M()
{
var e = new object();
switch (e)
{
case (((N.C.P $$"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
KeywordRecommending
)]
public
async
Task
TestAtBeginningOfSwitchStatement_AfterMultipleOpenParens_MemberAccessExpression2
()
{
await
VerifyKeywordAsync
(
@"namespace N
{
class C
{
void M()
{
var e = new object();
switch (e)
{
case (((N.C $$"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
KeywordRecommending
)]
public
async
Task
TestMissingAfterIsKeyword
()
{
...
...
src/EditorFeatures/CSharpTest2/Recommendations/OrKeywordRecommenderTests.cs
浏览文件 @
e31a0c4f
...
...
@@ -83,6 +83,40 @@ void M()
if (C2 is { P: (((1 $$"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
KeywordRecommending
)]
public
async
Task
TestAtBeginningOfSwitchStatement_AfterMultipleOpenParens_MemberAccessExpression
()
{
await
VerifyKeywordAsync
(
@"namespace N
{
class C
{
const int P = 1;
void M()
{
var e = new object();
switch (e)
{
case (((N.C.P $$"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
KeywordRecommending
)]
public
async
Task
TestAtBeginningOfSwitchStatement_AfterMultipleOpenParens_MemberAccessExpression2
()
{
await
VerifyKeywordAsync
(
@"namespace N
{
class C
{
void M()
{
var e = new object();
switch (e)
{
case (((N.C $$"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
KeywordRecommending
)]
public
async
Task
TestInsideSubpattern_AfterParenPair
()
{
...
...
@@ -126,6 +160,23 @@ void M()
if (e is C2.P $$"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
KeywordRecommending
)]
public
async
Task
TestAfterQualifiedName2
()
{
await
VerifyKeywordAsync
(
@"
namespace N
{
class C
{
const int P = 1;
void M()
{
var e = new object();
if (e is N.C.P $$"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
KeywordRecommending
)]
public
async
Task
TestAtBeginningOfSwitchExpression
()
{
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SyntaxTokenExtensions.cs
浏览文件 @
e31a0c4f
...
...
@@ -21,7 +21,7 @@ internal static partial class SyntaxTokenExtensions
public
static
bool
IsLastTokenOfNode
<
T
>(
this
SyntaxToken
token
,
[
NotNullWhen
(
true
)]
out
T
node
)
where
T
:
SyntaxNode
{
node
=
token
.
GetAncestor
<
T
>();
return
node
!=
null
&&
token
==
node
.
GetLastToken
();
return
node
!=
null
&&
token
==
node
.
GetLastToken
(
includeZeroWidth
:
true
);
}
public
static
bool
IsKindOrHasMatchingText
(
this
SyntaxToken
token
,
SyntaxKind
kind
)
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/SyntaxTreeExtensions.cs
浏览文件 @
e31a0c4f
...
...
@@ -1257,20 +1257,20 @@ public static bool IsAtStartOfPattern(this SyntaxTree syntaxTree, SyntaxToken le
{
leftToken
=
leftToken
.
GetPreviousTokenIfTouchingWord
(
position
);
// If we're dealing with an expression surrounded by one or more sets of open parentheses, we need to
// walk up the parens in order to see if we're actually at the start of a valid pattern or not.
// After recursing, we should be left with at most a single open paren to analyze.
if
(
leftToken
.
IsKind
(
SyntaxKind
.
OpenParenToken
))
{
if
(
leftToken
.
Parent
.
Is
Parent
Kind
(
SyntaxKind
.
ParenthesizedExpression
))
if
(
leftToken
.
Parent
.
IsKind
(
SyntaxKind
.
ParenthesizedExpression
))
{
return
IsAtStartOfPattern
(
syntaxTree
,
leftToken
.
Parent
.
Parent
.
GetFirstToken
(),
leftToken
.
Parent
.
Parent
.
SpanStart
);
// If we're dealing with an expression surrounded by one or more sets of open parentheses, we need to
// walk up the parens in order to see if we're actually at the start of a valid pattern or not.
var
tokenPrecedingParenthesizedExpression
=
leftToken
.
Parent
.
GetFirstToken
().
GetPreviousToken
();
return
IsAtStartOfPattern
(
syntaxTree
,
tokenPrecedingParenthesizedExpression
,
tokenPrecedingParenthesizedExpression
.
Span
.
End
+
1
);
}
#if !CODE_STYLE
if
(
leftToken
.
Parent
.
Is
Parent
Kind
(
SyntaxKind
.
ParenthesizedPattern
))
if
(
leftToken
.
Parent
.
IsKind
(
SyntaxKind
.
ParenthesizedPattern
))
{
return
IsAtStartOfPattern
(
syntaxTree
,
leftToken
.
Parent
.
Parent
.
GetFirstToken
(),
leftToken
.
Parent
.
Parent
.
SpanStart
)
;
return
true
;
}
#endif
}
...
...
@@ -1282,12 +1282,6 @@ public static bool IsAtStartOfPattern(this SyntaxTree syntaxTree, SyntaxToken le
return
true
;
}
// case ($
if
(
leftToken
.
IsKind
(
SyntaxKind
.
OpenParenToken
)
&&
leftToken
.
Parent
.
IsParentKind
(
SyntaxKind
.
CaseSwitchLabel
))
{
return
true
;
}
// e switch { $$
// e switch { ..., $$
if
(
leftToken
.
IsKind
(
SyntaxKind
.
OpenBraceToken
,
SyntaxKind
.
CommaToken
)
&&
leftToken
.
Parent
.
IsKind
(
SyntaxKind
.
SwitchExpression
))
...
...
@@ -1310,12 +1304,6 @@ public static bool IsAtStartOfPattern(this SyntaxTree syntaxTree, SyntaxToken le
return
true
;
}
// e is { P: ($$
if
(
leftToken
.
IsKind
(
SyntaxKind
.
OpenParenToken
)
&&
leftToken
.
Parent
.
IsParentKind
(
SyntaxKind
.
ConstantPattern
))
{
return
true
;
}
#if !CODE_STYLE
// e is 1 and $$
// e is 1 or $$
...
...
@@ -1329,12 +1317,6 @@ public static bool IsAtStartOfPattern(this SyntaxTree syntaxTree, SyntaxToken le
{
return
true
;
}
// e is ($$ 1 or 2)
if
(
leftToken
.
IsKind
(
SyntaxKind
.
OpenParenToken
)
&&
leftToken
.
Parent
.
IsKind
(
SyntaxKind
.
ParenthesizedPattern
))
{
return
true
;
}
#endif
return
false
;
...
...
@@ -1344,8 +1326,7 @@ public static bool IsAtEndOfPattern(this SyntaxTree syntaxTree, SyntaxToken left
{
#if CODE_STYLE
return
false
;
#endif
#else
var
originalLeftToken
=
leftToken
;
leftToken
=
leftToken
.
GetPreviousTokenIfTouchingWord
(
position
);
...
...
@@ -1383,30 +1364,55 @@ public static bool IsAtEndOfPattern(this SyntaxTree syntaxTree, SyntaxToken left
// e is int $$
if
(
leftToken
.
IsLastTokenOfNode
<
TypeSyntax
>(
out
var
typeSyntax
))
{
// If typeSyntax is part of a qualified name, we want to get the fully-qualified name so that we can
// later accurately perform the check comparing the right side of the BinaryExpressionSyntax to
// the typeSyntax.
while
(
typeSyntax
.
Parent
is
QualifiedNameSyntax
qualifiedNameSyntax
)
{
typeSyntax
=
qualifiedNameSyntax
;
}
var
binaryExpressionSyntax
=
typeSyntax
.
GetAncestor
<
BinaryExpressionSyntax
>();
if
(
binaryExpressionSyntax
!=
null
&&
binaryExpressionSyntax
.
OperatorToken
.
IsKind
(
SyntaxKind
.
IsKeyword
)
&&
binaryExpressionSyntax
.
Right
.
Contains
(
typeSyntax
)
)
binaryExpressionSyntax
.
Right
==
typeSyntax
)
{
return
true
;
}
}
// We need to include a special case for switch statement cases, as some are not currently parsed as patterns, e.g. case (1 $$
var
node
=
leftToken
.
Parent
;
// Getting rid of the extra parentheses to deal with cases such as 'case (((1 $$'
while
(
node
.
IsParentKind
(
SyntaxKind
.
ParenthesizedExpression
))
{
node
=
node
.
Parent
;
}
// case (1 $$
if
(
node
.
IsParentKind
(
SyntaxKind
.
CaseSwitchLabel
)
&&
node
.
Parent
.
IsParentKind
(
SyntaxKind
.
SwitchSection
))
if
(
IsAtEndOfSwitchStatementPattern
(
leftToken
))
{
return
true
;
}
return
false
;
static
bool
IsAtEndOfSwitchStatementPattern
(
SyntaxToken
leftToken
)
{
var
node
=
leftToken
.
Parent
;
// Walking up the tree for expressions such as 'case (((N.C.P $$'
while
(
node
.
IsParentKind
(
SyntaxKind
.
SimpleMemberAccessExpression
))
{
node
=
node
.
Parent
;
}
// Getting rid of the extra parentheses to deal with cases such as 'case (((1 $$'
while
(
node
.
IsParentKind
(
SyntaxKind
.
ParenthesizedExpression
))
{
node
=
node
.
Parent
;
}
// case (1 $$
if
(
node
.
IsParentKind
(
SyntaxKind
.
CaseSwitchLabel
)
&&
node
.
Parent
.
IsParentKind
(
SyntaxKind
.
SwitchSection
))
{
return
true
;
}
return
false
;
}
#endif
}
private
static
SyntaxToken
FindTokenOnLeftOfNode
(
SyntaxNode
node
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录