Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
eba2520d
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,发现更多精彩内容 >>
提交
eba2520d
编写于
3月 05, 2016
作者:
N
Neal Gafter
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Changes to pattern-matching implementation per code review.
上级
97d47292
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
118 addition
and
81 deletion
+118
-81
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
+26
-57
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs
...Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs
+19
-8
src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
...mpilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
+10
-8
src/Compilers/CSharp/Portable/Syntax/Syntax.xml
src/Compilers/CSharp/Portable/Syntax/Syntax.xml
+2
-1
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs
...rs/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs
+61
-7
未找到文件。
src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs
浏览文件 @
eba2520d
...
...
@@ -223,7 +223,6 @@ private BoundExpression BindIsPatternExpression(IsPatternExpressionSyntax node,
var
syntax
=
e
as
IsPatternExpressionSyntax
;
var
identifier
=
syntax
?.
Expression
as
IdentifierNameSyntax
;
if
(
identifier
==
null
)
throw
ExceptionUtilities
.
UnexpectedValue
(
syntax
?.
Expression
.
Kind
()
??
e
.
Kind
());
var
propName
=
identifier
.
Identifier
;
var
boundMember
=
BindPropertyPatternMember
(
type
,
identifier
,
diagnostics
);
var
boundPattern
=
BindPattern
(
syntax
.
Pattern
,
null
,
boundMember
.
Type
,
boundMember
.
HasErrors
,
diagnostics
);
result
.
Add
(
new
BoundSubPropertyPattern
(
e
,
boundMember
,
boundPattern
,
boundPattern
.
HasErrors
));
...
...
@@ -232,7 +231,7 @@ private BoundExpression BindIsPatternExpression(IsPatternExpressionSyntax node,
return
result
.
ToImmutableAndFree
();
}
// returns BadBoundExpression or Bound
ObjectInitializer
Member
// returns BadBoundExpression or Bound
PropertyPattern
Member
private
BoundExpression
BindPropertyPatternMember
(
TypeSymbol
patternType
,
IdentifierNameSyntax
memberName
,
...
...
@@ -275,29 +274,36 @@ private BoundExpression BindIsPatternExpression(IsPatternExpressionSyntax node,
switch
(
boundMember
.
Kind
)
{
case
BoundKind
.
FieldAccess
:
case
BoundKind
.
EventAccess
:
case
BoundKind
.
PropertyAccess
:
break
;
case
BoundKind
.
IndexerAccess
:
{
var
indexer
=
(
BoundIndexerAccess
)
boundMember
;
arguments
=
indexer
.
Arguments
;
argumentNamesOpt
=
indexer
.
ArgumentNamesOpt
;
argsToParamsOpt
=
indexer
.
ArgsToParamsOpt
;
argumentRefKindsOpt
=
indexer
.
ArgumentRefKindsOpt
;
expanded
=
indexer
.
Expanded
;
break
;
}
// TODO: Should a property pattern be capable of referencing an indexed property?
// https://github.com/dotnet/roslyn/issues/9375
//{
// var indexer = (BoundIndexerAccess)boundMember;
// arguments = indexer.Arguments;
// argumentNamesOpt = indexer.ArgumentNamesOpt;
// argsToParamsOpt = indexer.ArgsToParamsOpt;
// argumentRefKindsOpt = indexer.ArgumentRefKindsOpt;
// expanded = indexer.Expanded;
// break;
//}
case
BoundKind
.
DynamicIndexerAccess
:
{
var
indexer
=
(
BoundDynamicIndexerAccess
)
boundMember
;
arguments
=
indexer
.
Arguments
;
argumentNamesOpt
=
indexer
.
ArgumentNamesOpt
;
argumentRefKindsOpt
=
indexer
.
ArgumentRefKindsOpt
;
break
;
}
// TODO: Should a property pattern be capable of referencing a dynamic indexer?
// https://github.com/dotnet/roslyn/issues/9375
//{
// var indexer = (BoundDynamicIndexerAccess)boundMember;
// arguments = indexer.Arguments;
// argumentNamesOpt = indexer.ArgumentNamesOpt;
// argumentRefKindsOpt = indexer.ArgumentRefKindsOpt;
// break;
//}
case
BoundKind
.
EventAccess
:
// TODO: Should a property pattern be capable of referencing an event?
// https://github.com/dotnet/roslyn/issues/9515
default
:
return
BadSubpatternMemberAccess
(
boundMember
,
implicitReceiver
,
memberName
,
diagnostics
,
hasErrors
);
...
...
@@ -349,44 +355,7 @@ private BoundExpression BindIsPatternExpression(IsPatternExpressionSyntax node,
}
}
return
ToBadExpression
(
boundMember
,
LookupResultKind
.
NotAValue
);
}
private
Symbol
FindPropertyOrFieldByName
(
TypeSymbol
type
,
SyntaxToken
name
,
out
LookupResultKind
resultKind
,
ref
HashSet
<
DiagnosticInfo
>
useSiteDiagnostics
)
{
var
symbols
=
ArrayBuilder
<
Symbol
>.
GetInstance
();
var
lookupResult
=
LookupResult
.
GetInstance
();
this
.
LookupMembersWithFallback
(
lookupResult
,
type
,
name
.
ValueText
,
arity
:
0
,
useSiteDiagnostics
:
ref
useSiteDiagnostics
);
resultKind
=
lookupResult
.
Kind
;
Symbol
result
=
null
;
if
(
lookupResult
.
IsMultiViable
)
{
foreach
(
var
symbol
in
lookupResult
.
Symbols
)
{
if
(
symbol
.
Kind
==
SymbolKind
.
Property
||
symbol
.
Kind
==
SymbolKind
.
Field
)
{
if
(
result
!=
null
&&
symbol
!=
result
)
{
resultKind
=
LookupResultKind
.
Ambiguous
;
result
=
null
;
break
;
}
else
{
result
=
symbol
;
}
}
}
}
lookupResult
.
Free
();
return
result
;
return
ToBadExpression
(
boundMember
,
LookupResultKind
.
Inaccessible
);
}
private
BoundPattern
BindConstantPattern
(
...
...
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs
浏览文件 @
eba2520d
...
...
@@ -50,14 +50,25 @@ BoundExpression TranslatePattern(BoundExpression input, BoundPattern pattern)
{
var
subProperty
=
(
pat
.
Subpatterns
[
i
].
Member
as
BoundPropertyPatternMember
)?.
MemberSymbol
;
var
subPattern
=
pat
.
Subpatterns
[
i
].
Pattern
;
var
subExpression
=
subProperty
?.
Kind
==
SymbolKind
.
Field
?
_factory
.
Field
(
input
,
(
FieldSymbol
)
subProperty
)
:
subProperty
?.
Kind
==
SymbolKind
.
Property
?
_factory
.
Call
(
input
,
((
PropertySymbol
)
subProperty
).
GetMethod
)
:
(
BoundExpression
)
new
BoundBadExpression
(
_factory
.
Syntax
,
LookupResultKind
.
Inaccessible
,
ImmutableArray
<
Symbol
>.
Empty
,
ImmutableArray
<
BoundNode
>.
Empty
,
pat
.
Type
);
BoundExpression
subExpression
;
switch
(
subProperty
?.
Kind
)
{
case
SymbolKind
.
Field
:
subExpression
=
_factory
.
Field
(
input
,
(
FieldSymbol
)
subProperty
);
break
;
case
SymbolKind
.
Property
:
subExpression
=
_factory
.
Call
(
input
,
((
PropertySymbol
)
subProperty
).
GetMethod
);
break
;
case
SymbolKind
.
Event
:
// TODO: should a property pattern be capable of referencing an event?
// https://github.com/dotnet/roslyn/issues/9515
default
:
subExpression
=
new
BoundBadExpression
(
_factory
.
Syntax
,
LookupResultKind
.
Inaccessible
,
ImmutableArray
<
Symbol
>.
Empty
,
ImmutableArray
<
BoundNode
>.
Empty
,
pat
.
Type
);
break
;
}
var
partialMatch
=
this
.
TranslatePattern
(
subExpression
,
subPattern
);
matched
=
_factory
.
LogicalAnd
(
matched
,
partialMatch
);
}
...
...
src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs
浏览文件 @
eba2520d
...
...
@@ -53,10 +53,7 @@ private CSharpSyntaxNode ParseTypeOrPattern()
// X.Y.Z { ... } : PropertyPattern
else
if
(
tk
==
SyntaxKind
.
OpenBraceToken
)
{
var
open
=
this
.
EatToken
(
SyntaxKind
.
OpenBraceToken
);
var
list
=
this
.
ParseSubPropertyPatternList
(
ref
open
);
var
close
=
this
.
EatToken
(
SyntaxKind
.
CloseBraceToken
);
node
=
_syntaxFactory
.
PropertyPattern
(
type
,
open
,
list
,
close
);
node
=
ParsePropertyPatternBody
(
type
);
}
// X.Y.Z id
else
if
(
this
.
IsTrueIdentifier
())
...
...
@@ -99,6 +96,14 @@ private CSharpSyntaxNode ParseTypeOrPattern()
return
node
;
}
private
PropertyPatternSyntax
ParsePropertyPatternBody
(
TypeSyntax
type
)
{
var
open
=
this
.
EatToken
(
SyntaxKind
.
OpenBraceToken
);
var
list
=
this
.
ParseSubPropertyPatternList
(
ref
open
);
var
close
=
this
.
EatToken
(
SyntaxKind
.
CloseBraceToken
);
return
_syntaxFactory
.
PropertyPattern
(
type
,
open
,
list
,
close
);
}
private
SubRecursivePatternListSyntax
ParseSubRecursivePatternList
()
{
if
(
this
.
IsIncrementalAndFactoryContextMatches
&&
this
.
CurrentNodeKind
==
SyntaxKind
.
SubRecursivePatternList
)
...
...
@@ -246,10 +251,7 @@ private CSharpSyntaxNode ParseExpressionOrPattern()
// X.Y.Z { ... } : PropertyPattern
else
if
(
tk
==
SyntaxKind
.
OpenBraceToken
)
{
var
openBrace
=
this
.
EatToken
(
SyntaxKind
.
OpenBraceToken
);
var
contents
=
this
.
ParseSubPropertyPatternList
(
ref
openBrace
);
var
closeBrace
=
this
.
EatToken
(
SyntaxKind
.
CloseBraceToken
);
node
=
_syntaxFactory
.
PropertyPattern
(
type
,
openBrace
,
contents
,
closeBrace
);
node
=
ParsePropertyPatternBody
(
type
);
}
// X.Y.Z id
else
if
(
this
.
IsTrueIdentifier
())
...
...
src/Compilers/CSharp/Portable/Syntax/Syntax.xml
浏览文件 @
eba2520d
...
...
@@ -1724,7 +1724,8 @@
</Field>
<Field
Name=
"SubPatterns"
Type=
"SeparatedSyntaxList<ExpressionSyntax>"
>
<PropertyComment>
<summary>
SeparatedSyntaxList of ExpressionSyntax representing the list of "ID is Pattern" expressions in the property pattern.
</summary>
<summary>
The list of "ID is Pattern" expressions in the property pattern represented as IsPatternExpressionSyntax nodes.
</summary>
</PropertyComment>
</Field>
<Field
Name=
"CloseBraceToken"
Type=
"SyntaxToken"
>
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs
浏览文件 @
eba2520d
...
...
@@ -1042,14 +1042,16 @@ public static void Main()
object o = nameof(Main);
Console.WriteLine(o is P { Good is 4 });
Console.WriteLine(o is P { NotFound is 4 });
Console.WriteLine(o is P { Unreadable is 4 });
Console.WriteLine(o is P { Unreadable1 is 4 });
Console.WriteLine(o is P { Unreadable2 is 4 });
}
}
class P
{
public int Good = 2;
public int Unreadable { set { } }
public int Unreadable1 { set { } }
public int Unreadable2 { set { } protected get { return 0; } }
}
"
;
var
compilation
=
CreateCompilationWithMscorlib45
(
source
,
options
:
TestOptions
.
DebugExe
,
parseOptions
:
patternParseOptions
);
...
...
@@ -1058,15 +1060,18 @@ class P
// (9,36): error CS0117: 'P' does not contain a definition for 'NotFound'
// Console.WriteLine(o is P { NotFound is 4 });
Diagnostic
(
ErrorCode
.
ERR_NoSuchMember
,
"NotFound"
).
WithArguments
(
"P"
,
"NotFound"
).
WithLocation
(
9
,
36
),
// (10,36): error CS0154: The property or indexer 'P.Unreadable' cannot be used in this context because it lacks the get accessor
// Console.WriteLine(o is P { Unreadable is 4 });
Diagnostic
(
ErrorCode
.
ERR_PropertyLacksGet
,
"Unreadable"
).
WithArguments
(
"P.Unreadable"
).
WithLocation
(
10
,
36
)
// (10,36): error CS0154: The property or indexer 'P.Unreadable1' cannot be used in this context because it lacks the get accessor
// Console.WriteLine(o is P { Unreadable1 is 4 });
Diagnostic
(
ErrorCode
.
ERR_PropertyLacksGet
,
"Unreadable1"
).
WithArguments
(
"P.Unreadable1"
).
WithLocation
(
10
,
36
),
// (11,36): error CS0271: The property or indexer 'P.Unreadable2' cannot be used in this context because the get accessor is inaccessible
// Console.WriteLine(o is P { Unreadable2 is 4 });
Diagnostic
(
ErrorCode
.
ERR_InaccessibleGetter
,
"Unreadable2"
).
WithArguments
(
"P.Unreadable2"
).
WithLocation
(
11
,
36
)
);
var
tree
=
compilation
.
SyntaxTrees
.
Single
();
var
model
=
compilation
.
GetSemanticModel
(
tree
);
var
propPats
=
tree
.
GetRoot
().
DescendantNodes
().
OfType
<
IsPatternExpressionSyntax
>().
Where
(
e
=>
e
.
Parent
is
PropertyPatternSyntax
).
ToArray
();
Assert
.
Equal
(
3
,
propPats
.
Length
);
Assert
.
Equal
(
4
,
propPats
.
Length
);
var
p
=
propPats
[
0
].
Expression
;
// 'Good' in Good is 4
var
si
=
model
.
GetSymbolInfo
(
p
);
...
...
@@ -1081,11 +1086,19 @@ class P
Assert
.
Equal
(
CandidateReason
.
None
,
si
.
CandidateReason
);
Assert
.
True
(
si
.
CandidateSymbols
.
IsDefaultOrEmpty
);
p
=
propPats
[
2
].
Expression
;
// 'Unreadable
' in Unreadable
is 4
p
=
propPats
[
2
].
Expression
;
// 'Unreadable
1' in Unreadable1
is 4
si
=
model
.
GetSymbolInfo
(
p
);
Assert
.
Null
(
si
.
Symbol
);
Assert
.
Equal
(
CandidateReason
.
NotAValue
,
si
.
CandidateReason
);
Assert
.
Equal
(
1
,
si
.
CandidateSymbols
.
Length
);
Assert
.
Equal
(
"Unreadable1"
,
si
.
CandidateSymbols
[
0
].
Name
);
p
=
propPats
[
3
].
Expression
;
// 'Unreadable2' in Unreadable2 is 4
si
=
model
.
GetSymbolInfo
(
p
);
Assert
.
Null
(
si
.
Symbol
);
Assert
.
Equal
(
CandidateReason
.
NotAValue
,
si
.
CandidateReason
);
Assert
.
Equal
(
1
,
si
.
CandidateSymbols
.
Length
);
Assert
.
Equal
(
"Unreadable2"
,
si
.
CandidateSymbols
[
0
].
Name
);
}
[
Fact
,
WorkItem
(
9284
,
"https://github.com/dotnet/roslyn/issues/9284"
)]
...
...
@@ -1129,6 +1142,8 @@ interface I3 : I1, I2 { }
Assert
.
Null
(
si
.
Symbol
);
Assert
.
Equal
(
CandidateReason
.
Ambiguous
,
si
.
CandidateReason
);
Assert
.
Equal
(
2
,
si
.
CandidateSymbols
.
Length
);
Assert
.
Equal
(
"I1"
,
si
.
CandidateSymbols
[
0
].
ContainingSymbol
.
Name
);
Assert
.
Equal
(
"I2"
,
si
.
CandidateSymbols
[
1
].
ContainingSymbol
.
Name
);
}
[
Fact
(
Skip
=
"https://github.com/dotnet/roslyn/issues/9284"
),
WorkItem
(
9284
,
"https://github.com/dotnet/roslyn/issues/9284"
)]
...
...
@@ -1170,6 +1185,45 @@ class Point
Assert
.
Equal
(
CandidateReason
.
StaticInstanceMismatch
,
si
.
CandidateReason
);
}
[
Fact
]
public
void
InaccessibleNamedProperty
()
{
var
source
=
@"
using System;
public class Program
{
public static void Main()
{
object o = null;
Console.WriteLine(o is Point { X is 4 });
}
}
class Point
{
protected int X => 0;
}
"
;
var
compilation
=
CreateCompilationWithMscorlib45
(
source
,
options
:
TestOptions
.
DebugExe
,
parseOptions
:
patternParseOptions
);
// TODO: need a better diagnostic for this
compilation
.
VerifyDiagnostics
(
// (8,40): error CS0122: 'Point.X' is inaccessible due to its protection level
// Console.WriteLine(o is Point { X is 4 });
Diagnostic
(
ErrorCode
.
ERR_BadAccess
,
"X"
).
WithArguments
(
"Point.X"
).
WithLocation
(
8
,
40
)
);
var
tree
=
compilation
.
SyntaxTrees
.
Single
();
var
model
=
compilation
.
GetSemanticModel
(
tree
);
var
propPats
=
tree
.
GetRoot
().
DescendantNodes
().
OfType
<
PropertyPatternSyntax
>().
SelectMany
(
s
=>
s
.
SubPatterns
).
OfType
<
IsPatternExpressionSyntax
>().
ToArray
();
Assert
.
Equal
(
1
,
propPats
.
Length
);
var
p
=
propPats
[
0
].
Expression
;
// 'X' in "X is 4"
var
si
=
model
.
GetSymbolInfo
(
p
);
Assert
.
Null
(
si
.
Symbol
);
Assert
.
Equal
(
1
,
si
.
CandidateSymbols
.
Length
);
Assert
.
Equal
(
CandidateReason
.
Inaccessible
,
si
.
CandidateReason
);
}
private
static
void
VerifyModelForDeclarationPattern
(
SemanticModel
model
,
DeclarationPatternSyntax
decl
,
params
IdentifierNameSyntax
[]
references
)
{
var
symbol
=
model
.
GetDeclaredSymbol
(
decl
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录