Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
044f5b85
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,发现更多精彩内容 >>
提交
044f5b85
编写于
8月 21, 2020
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Doc things more
上级
98e63d49
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
106 addition
and
10 deletion
+106
-10
src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs
...tion/CompletionProviders/SymbolCompletionProviderTests.cs
+43
-1
src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner.cs
...able/Recommendations/CSharpRecommendationServiceRunner.cs
+1
-1
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SyntaxNodeExtensions.cs
...nsions/Compiler/CSharp/Extensions/SyntaxNodeExtensions.cs
+62
-8
未找到文件。
src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs
浏览文件 @
044f5b85
...
...
@@ -8074,7 +8074,7 @@ public void goo()
[
WorkItem
(
1109319
,
"http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1109319"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
WithinChainOfConditionalAccesses
()
public
async
Task
WithinChainOfConditionalAccesses
1
()
{
var
markup
=
@"
class Program
...
...
@@ -8093,6 +8093,48 @@ class D { public int e; }";
await
VerifyItemExistsAsync
(
markup
,
"b"
);
}
[
WorkItem
(
1109319
,
"http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1109319"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
WithinChainOfConditionalAccesses2
()
{
var
markup
=
@"
class Program
{
static void Main(string[] args)
{
A a;
var x = a?.b?.$$c?.d.e;
}
}
class A { public B b; }
class B { public C c; }
class C { public D d; }
class D { public int e; }"
;
await
VerifyItemExistsAsync
(
markup
,
"c"
);
}
[
WorkItem
(
1109319
,
"http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1109319"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
WithinChainOfConditionalAccesses3
()
{
var
markup
=
@"
class Program
{
static void Main(string[] args)
{
A a;
var x = a?.b?.c?.$$d.e;
}
}
class A { public B b; }
class B { public C c; }
class C { public D d; }
class D { public int e; }"
;
await
VerifyItemExistsAsync
(
markup
,
"d"
);
}
[
WorkItem
(
843466
,
"http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/843466"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
NestedAttributeAccessibleOnSelf
()
...
...
src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner.cs
浏览文件 @
044f5b85
...
...
@@ -129,7 +129,7 @@ private ImmutableArray<ISymbol> GetSymbolsOffOfContainer()
}
else
if
(
node
.
Kind
()
==
SyntaxKind
.
MemberBindingExpression
)
{
var
parentConditionalAccess
=
node
.
Get
Roo
tConditionalAccessExpression
();
var
parentConditionalAccess
=
node
.
Get
Paren
tConditionalAccessExpression
();
return
GetSymbolsOffOfConditionalReceiver
(
parentConditionalAccess
.
Expression
);
}
else
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Extensions/SyntaxNodeExtensions.cs
浏览文件 @
044f5b85
...
...
@@ -272,10 +272,7 @@ public static SyntaxList<AttributeListSyntax> GetAttributeLists(this SyntaxNode
_
=>
default
,
};
/// <summary>
/// <inheritdoc cref="ISyntaxFacts.GetRootConditionalAccessExpression(SyntaxNode)"/>
/// </summary>>
public
static
ConditionalAccessExpressionSyntax
?
GetRootConditionalAccessExpression
(
this
SyntaxNode
?
node
)
public
static
ConditionalAccessExpressionSyntax
?
GetParentConditionalAccessExpression
(
this
SyntaxNode
?
node
)
{
// Walk upwards based on the grammar/parser rules around ?. expressions (can be seen in
// LanguageParser.ParseConsequenceSyntax).
...
...
@@ -295,28 +292,85 @@ public static SyntaxList<AttributeListSyntax> GetAttributeLists(this SyntaxNode
current
=
current
.
Parent
;
}
// Effectively, if we're on the RHS of hte ? we have to walk up the RHS spine first until we hit the first
// conditional access.
while
(
current
.
IsKind
(
SyntaxKind
.
InvocationExpression
,
SyntaxKind
.
ElementAccessExpression
,
SyntaxKind
.
SimpleMemberAccessExpression
,
SyntaxKind
.
MemberBindingExpression
,
SyntaxKind
.
ElementBindingExpression
))
SyntaxKind
.
ElementBindingExpression
)
&&
current
.
Parent
is
not
ConditionalAccessExpressionSyntax
)
{
current
=
current
.
Parent
;
}
// Two cases we have to care about:
// 1. a?.b.$$c.d and
// 2. a?.b.$$c.d?.e...
//
// Note that `a?.b.$$c.d?.e.f?.g.h.i` falls into the same bucket as two. i.e. the parts after `.e` are
// lower in the tree and are not seen as we walk upwards.
//
//
// To get the root ?. (the one after the `a`) we have to potentially consume the first ?. on the RHS of the
// right spine (i.e. the one after `d`). Once we do this, we then see if that itself is on the RHS of a
// another conditional, and if so we hten return the one on the left. i.e. for '2' this goes in this direction:
//
// a?.b.$$c.d?.e
// ----->
// then
//
// <---------
//
// Note that this only one CAE consumption on both sides. GetRootConditionalAccessExpression can be used to
// get the root parent in a case like:
//
// x?.y?.z?.a?.b.$$c.d?.e.f?.g.h.i
//
// It will do:
//
// ----->
// <---------
// <---
// <---
// <---
if
(
current
.
IsParentKind
(
SyntaxKind
.
ConditionalAccessExpression
,
out
ConditionalAccessExpressionSyntax
?
conditional
)
&&
conditional
.
Expression
==
current
)
{
current
=
conditional
;
}
if
(
current
.
IsParentKind
(
SyntaxKind
.
ConditionalAccessExpression
,
out
conditional
)
&&
conditional
.
WhenNotNull
==
current
)
{
current
=
conditional
;
}
return
current
as
ConditionalAccessExpressionSyntax
;
}
/// <summary>
/// <inheritdoc cref="ISyntaxFacts.GetRootConditionalAccessExpression(SyntaxNode)"/>
/// </summary>>
public
static
ConditionalAccessExpressionSyntax
?
GetRootConditionalAccessExpression
(
this
SyntaxNode
?
node
)
{
// Once we've walked up the entire RHS, now we continually walk up the conditional accesses until we're at
// the root. For example, if we have `a?.b` and we're on the `.b`, this will give `a?.b`. Similarly with
// `a?.b?.c` if we're on either `.b` or `.c` this will result in `a?.b?.c` (i.e. the root of this CAE
// sequence).
var
current
=
node
.
GetParentConditionalAccessExpression
();
while
(
current
.
IsParentKind
(
SyntaxKind
.
ConditionalAccessExpression
,
out
ConditionalAccessExpressionSyntax
?
conditional
)
&&
conditional
.
WhenNotNull
==
current
)
conditional
.
WhenNotNull
==
current
)
{
current
=
c
urrent
.
Parent
;
current
=
c
onditional
;
}
return
current
as
ConditionalAccessExpressionSyntax
;
return
current
;
}
public
static
ConditionalAccessExpressionSyntax
?
GetInnerMostConditionalAccessExpression
(
this
SyntaxNode
node
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录