Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
3efd039e
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,发现更多精彩内容 >>
未验证
提交
3efd039e
编写于
3月 28, 2018
作者:
F
Fredric Silberberg
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Addressed PR feedback, updated ILocalFunctionOperation to final design specified in review.
上级
06dcac6a
变更
17
展开全部
隐藏空白更改
内联
并排
Showing
17 changed file
with
273 addition
and
266 deletion
+273
-266
src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
+18
-15
src/Compilers/CSharp/Portable/BoundTree/Statement.cs
src/Compilers/CSharp/Portable/BoundTree/Statement.cs
+0
-5
src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
+1
-1
src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
...pilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
+8
-0
src/Compilers/CSharp/Portable/FlowAnalysis/AbstractRegionControlFlowPass.cs
...rp/Portable/FlowAnalysis/AbstractRegionControlFlowPass.cs
+1
-2
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.LocalFunctions.cs
...harp/Portable/FlowAnalysis/DataFlowPass.LocalFunctions.cs
+1
-1
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.Tree.cs
...e/Lowering/LambdaRewriter/LambdaRewriter.Analysis.Tree.cs
+1
-1
src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
...lers/CSharp/Portable/Operations/CSharpOperationFactory.cs
+5
-3
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenLocalFunctionTests.cs
...ers/CSharp/Test/Emit/CodeGen/CodeGenLocalFunctionTests.cs
+9
-8
src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILocalFunctionStatement.cs
...tic/IOperation/IOperationTests_ILocalFunctionStatement.cs
+152
-138
src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs
...peration/IOperationTests_IParameterReferenceExpression.cs
+33
-34
src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs
...ilers/Core/Portable/Generated/Operations.xml.Generated.cs
+19
-24
src/Compilers/Core/Portable/Operations/ILocalFunctionOperation.cs
...ilers/Core/Portable/Operations/ILocalFunctionOperation.cs
+5
-10
src/Compilers/Core/Portable/Operations/OperationCloner.cs
src/Compilers/Core/Portable/Operations/OperationCloner.cs
+1
-1
src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
+1
-2
src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs
...t/Utilities/Portable/Compilation/OperationTreeVerifier.cs
+11
-6
src/Test/Utilities/Portable/Compilation/TestOperationVisitor.cs
...st/Utilities/Portable/Compilation/TestOperationVisitor.cs
+7
-15
未找到文件。
src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
浏览文件 @
3efd039e
...
...
@@ -492,28 +492,29 @@ private BoundStatement BindLocalFunctionStatement(LocalFunctionStatementSyntax n
var
hasErrors
=
localSymbol
.
ScopeBinder
.
ValidateDeclarationNameConflictsInScope
(
localSymbol
,
diagnostics
);
BoundBlock
blockBody
=
node
.
Body
!=
null
?
BindEmbeddedBlock
(
node
.
Body
,
diagnostics
)
:
null
;
DiagnosticBag
expressionBodyDiagnostics
=
null
;
BoundBlock
blockBody
=
null
;
BoundBlock
expressionBody
=
null
;
if
(
node
.
Expression
Body
!=
null
)
if
(
node
.
Body
!=
null
)
{
expressionBodyDiagnostics
=
node
.
Body
==
null
?
diagnostics
:
new
DiagnosticBag
();
expressionBody
=
BindExpressionBodyAsBlock
(
node
.
ExpressionBody
,
expressionBodyDiagnostics
);
blockBody
=
runAnalysis
(
BindEmbeddedBlock
(
node
.
Body
,
diagnostics
),
diagnostics
);
if
(
node
.
ExpressionBody
!=
null
)
{
var
expressionBodyDiagnostics
=
new
DiagnosticBag
();
expressionBody
=
runAnalysis
(
BindExpressionBodyAsBlock
(
node
.
ExpressionBody
,
expressionBodyDiagnostics
),
expressionBodyDiagnostics
);
}
}
else
if
(
node
.
Body
==
null
&&
node
.
ExpressionBody
==
null
)
else
if
(
node
.
ExpressionBody
!=
null
)
{
expressionBody
=
runAnalysis
(
BindExpressionBodyAsBlock
(
node
.
ExpressionBody
,
diagnostics
),
diagnostics
);
}
else
{
hasErrors
=
true
;
diagnostics
.
Add
(
ErrorCode
.
ERR_LocalFunctionMissingBody
,
localSymbol
.
Locations
[
0
],
localSymbol
);
}
Debug
.
Assert
(
blockBody
!=
null
||
expressionBody
!=
null
||
hasErrors
);
Debug
.
Assert
((
expressionBody
==
null
)
==
(
expressionBodyDiagnostics
==
null
));
if
(
blockBody
!=
null
||
expressionBody
!=
null
)
{
localSymbol
.
ComputeReturnType
();
runAnalysis
(
ref
blockBody
,
diagnostics
);
runAnalysis
(
ref
expressionBody
,
expressionBodyDiagnostics
);
}
Debug
.
Assert
(
blockBody
!=
null
||
expressionBody
!=
null
||
hasErrors
);
localSymbol
.
GetDeclarationDiagnostics
(
diagnostics
);
...
...
@@ -522,7 +523,7 @@ private BoundStatement BindLocalFunctionStatement(LocalFunctionStatementSyntax n
return
new
BoundLocalFunctionStatement
(
node
,
localSymbol
,
blockBody
,
expressionBody
,
hasErrors
);
void
runAnalysis
(
ref
BoundBlock
block
,
DiagnosticBag
blockDiagnostics
)
BoundBlock
runAnalysis
(
BoundBlock
block
,
DiagnosticBag
blockDiagnostics
)
{
if
(
block
!=
null
)
{
...
...
@@ -543,6 +544,8 @@ void runAnalysis(ref BoundBlock block, DiagnosticBag blockDiagnostics)
}
}
}
return
block
;
}
}
...
...
src/Compilers/CSharp/Portable/BoundTree/Statement.cs
浏览文件 @
3efd039e
...
...
@@ -21,11 +21,6 @@ internal partial class BoundBadStatement
protected
override
ImmutableArray
<
BoundNode
>
Children
=>
this
.
ChildBoundNodes
;
}
partial
class
BoundLocalFunctionStatement
{
protected
override
ImmutableArray
<
BoundNode
>
Children
=>
ImmutableArray
.
Create
<
BoundNode
>(
this
.
BlockBody
,
this
.
ExpressionBody
);
}
partial
class
BoundFixedStatement
{
protected
override
ImmutableArray
<
BoundNode
>
Children
=>
ImmutableArray
.
Create
<
BoundNode
>(
this
.
Declarations
,
this
.
Body
);
...
...
src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
浏览文件 @
3efd039e
...
...
@@ -29,7 +29,7 @@ internal sealed partial class BoundLocalFunctionStatement : IBoundLambdaOrFuncti
SyntaxNode
IBoundLambdaOrFunction
.
Syntax
{
get
{
return
Syntax
;
}
}
BoundBlock
IBoundLambdaOrFunction
.
Body
{
get
=>
BlockBody
??
Expression
Body
;
}
BoundBlock
IBoundLambdaOrFunction
.
Body
{
get
=>
this
.
Body
;
}
}
internal
sealed
partial
class
BoundLambda
:
IBoundLambdaOrFunction
...
...
src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
浏览文件 @
3efd039e
...
...
@@ -1396,7 +1396,15 @@ private CSharpSyntaxNode GetBindingRoot(CSharpSyntaxNode node)
{
case
SyntaxKind
.
ThisConstructorInitializer
:
case
SyntaxKind
.
BaseConstructorInitializer
:
return
current
;
case
SyntaxKind
.
ArrowExpressionClause
:
// If this is an arrow expression on a local function statement, then our bindable root is actually our parent syntax as it's
// a statement in a function. If this is returned directly in IOperation, we'll end up with a separate tree.
if
(
current
.
ParentOrStructuredTriviaParent
!=
null
&&
current
.
ParentOrStructuredTriviaParent
.
Kind
()
==
SyntaxKind
.
LocalFunctionStatement
)
{
return
current
.
ParentOrStructuredTriviaParent
;
}
return
current
;
}
}
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/AbstractRegionControlFlowPass.cs
浏览文件 @
3efd039e
...
...
@@ -36,8 +36,7 @@ public override BoundNode VisitLambda(BoundLambda node)
public
override
BoundNode
VisitLocalFunctionStatement
(
BoundLocalFunctionStatement
node
)
{
VisitLocalFunctionOrLambda
(
node
.
BlockBody
);
VisitLocalFunctionOrLambda
(
node
.
ExpressionBody
);
VisitLocalFunctionOrLambda
(
node
.
Body
);
return
null
;
}
...
...
src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.LocalFunctions.cs
浏览文件 @
3efd039e
...
...
@@ -156,7 +156,7 @@ public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatemen
PendingBranches
.
Add
(
new
PendingBranch
(
null
,
this
.
State
));
}
VisitAlways
(
localFunc
.
B
lockBody
??
localFunc
.
ExpressionB
ody
);
VisitAlways
(
localFunc
.
Body
);
RestorePending
(
oldPending2
);
// process any forward branches within the lambda body
ImmutableArray
<
PendingBranch
>
pendingReturns
=
RemoveReturns
();
RestorePending
(
oldPending
);
...
...
src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.Tree.cs
浏览文件 @
3efd039e
...
...
@@ -386,7 +386,7 @@ public override BoundNode VisitLambda(BoundLambda node)
}
public
override
BoundNode
VisitLocalFunctionStatement
(
BoundLocalFunctionStatement
node
)
=>
VisitClosure
(
node
.
Symbol
.
OriginalDefinition
,
node
.
B
lockBody
??
node
.
ExpressionB
ody
);
=>
VisitClosure
(
node
.
Symbol
.
OriginalDefinition
,
node
.
Body
);
public
override
BoundNode
VisitCall
(
BoundCall
node
)
{
...
...
src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
浏览文件 @
3efd039e
...
...
@@ -774,13 +774,15 @@ private IAnonymousFunctionOperation CreateBoundLambdaOperation(BoundLambda bound
private
ILocalFunctionOperation
CreateBoundLocalFunctionStatementOperation
(
BoundLocalFunctionStatement
boundLocalFunctionStatement
)
{
IMethodSymbol
symbol
=
boundLocalFunctionStatement
.
Symbol
;
Lazy
<
IBlockOperation
>
blockBody
=
new
Lazy
<
IBlockOperation
>(()
=>
(
IBlockOperation
)
Create
(
boundLocalFunctionStatement
.
BlockBody
));
Lazy
<
IBlockOperation
>
expressionBody
=
new
Lazy
<
IBlockOperation
>(()
=>
(
IBlockOperation
)
Create
(
boundLocalFunctionStatement
.
ExpressionBody
));
Lazy
<
IBlockOperation
>
body
=
new
Lazy
<
IBlockOperation
>(()
=>
(
IBlockOperation
)
Create
(
boundLocalFunctionStatement
.
Body
));
Lazy
<
IBlockOperation
>
ignoredBody
=
new
Lazy
<
IBlockOperation
>(()
=>
boundLocalFunctionStatement
.
BlockBody
!=
null
&&
boundLocalFunctionStatement
.
ExpressionBody
!=
null
?
(
IBlockOperation
)
Create
(
boundLocalFunctionStatement
.
ExpressionBody
)
:
null
);
SyntaxNode
syntax
=
boundLocalFunctionStatement
.
Syntax
;
ITypeSymbol
type
=
null
;
Optional
<
object
>
constantValue
=
default
(
Optional
<
object
>);
bool
isImplicit
=
boundLocalFunctionStatement
.
WasCompilerGenerated
;
return
new
LazyLocalFunctionStatement
(
symbol
,
b
lockBody
,
expression
Body
,
_semanticModel
,
syntax
,
type
,
constantValue
,
isImplicit
);
return
new
LazyLocalFunctionStatement
(
symbol
,
b
ody
,
ignored
Body
,
_semanticModel
,
syntax
,
type
,
constantValue
,
isImplicit
);
}
private
IOperation
CreateBoundConversionOperation
(
BoundConversion
boundConversion
)
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenLocalFunctionTests.cs
浏览文件 @
3efd039e
using
Microsoft.CodeAnalysis.CSharp.Symbols
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.CSharp.Test.Utilities
;
using
Microsoft.CodeAnalysis.Operations
;
using
Microsoft.CodeAnalysis.Test.Utilities
;
using
Roslyn.Test.Utilities
;
using
System
;
...
...
@@ -90,10 +91,12 @@ static void Main(string[] args)
}"
);
var
tree
=
comp
.
SyntaxTrees
.
Single
();
var
model
=
comp
.
GetSemanticModel
(
tree
,
ignoreAccessibility
:
false
);
var
creation
=
tree
.
GetRoot
().
DescendantNodes
().
OfType
<
ObjectCreationExpressionSyntax
>().
Single
();
var
localFunction
=
tree
.
GetRoot
().
DescendantNodes
().
OfType
<
LocalFunctionStatementSyntax
>().
Single
();
var
creation
=
localFunction
.
DescendantNodes
().
OfType
<
ObjectCreationExpressionSyntax
>().
Single
();
var
operation
=
model
.
GetOperation
(
creation
);
Assert
.
NotNull
(
operation
);
var
objectCreationOperation
=
model
.
GetOperation
(
creation
);
var
localFunctionOperation
=
(
ILocalFunctionOperation
)
model
.
GetOperation
(
localFunction
);
Assert
.
NotNull
(
objectCreationOperation
);
comp
.
VerifyOperationTree
(
creation
,
expectedOperationTree
:
@"
...
...
@@ -103,11 +106,9 @@ static void Main(string[] args)
null
"
);
Assert
.
Equal
(
OperationKind
.
ExpressionStatement
,
operation
.
Parent
.
Kind
);
Assert
.
Equal
(
OperationKind
.
Block
,
operation
.
Parent
.
Parent
.
Kind
);
// We didn't bind the expression body, but should. See issue https://github.com/dotnet/roslyn/issues/24650
// The block from the previous assert, should have a parent
Assert
.
Null
(
operation
.
Parent
.
Parent
.
Parent
);
Assert
.
Equal
(
OperationKind
.
ExpressionStatement
,
objectCreationOperation
.
Parent
.
Kind
);
Assert
.
Equal
(
OperationKind
.
Block
,
objectCreationOperation
.
Parent
.
Parent
.
Kind
);
Assert
.
Equal
(
localFunctionOperation
.
IgnoredBody
,
objectCreationOperation
.
Parent
.
Parent
);
var
info
=
model
.
GetTypeInfo
(
creation
);
Assert
.
Equal
(
"System.Object"
,
info
.
Type
.
ToTestDisplayString
());
...
...
src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILocalFunctionStatement.cs
浏览文件 @
3efd039e
此差异已折叠。
点击以展开。
src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs
浏览文件 @
3efd039e
...
...
@@ -1038,40 +1038,39 @@ static IEnumerable<T> MyIterator<T>(IEnumerable<T> source, Func<T, bool> predica
"
;
string
expectedOperationTree
=
@"
ILocalFunctionOperation (Symbol: System.Collections.Generic.IEnumerable<T> Iterator()) (OperationKind.LocalFunction, Type: null) (Syntax: 'IEnumerable ... }')
Block Body:
IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }')
IForEachLoopOperation (LoopKind.ForEach) (OperationKind.Loop, Type: null) (Syntax: 'foreach (va ... rn element;')
Locals: Local_1: T element
LoopControlVariable:
IVariableDeclaratorOperation (Symbol: T element) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'var')
Initializer:
null
Collection:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Collections.Generic.IEnumerable<T>, IsImplicit) (Syntax: 'source')
Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
IParameterReferenceOperation: source (OperationKind.ParameterReference, Type: System.Collections.Generic.IEnumerable<T>) (Syntax: 'source')
Body:
IConditionalOperation (OperationKind.Conditional, Type: null) (Syntax: 'if (predica ... rn element;')
Condition:
IInvocationOperation (virtual System.Boolean System.Func<T, System.Boolean>.Invoke(T arg)) (OperationKind.Invocation, Type: System.Boolean) (Syntax: 'predicate(element)')
Instance Receiver:
IParameterReferenceOperation: predicate (OperationKind.ParameterReference, Type: System.Func<T, System.Boolean>) (Syntax: 'predicate')
Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: arg) (OperationKind.Argument, Type: null) (Syntax: 'element')
ILocalReferenceOperation: element (OperationKind.LocalReference, Type: T) (Syntax: 'element')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
WhenTrue:
IReturnOperation (OperationKind.YieldReturn, Type: null) (Syntax: 'yield return element;')
ReturnedValue:
ILocalReferenceOperation: element (OperationKind.LocalReference, Type: T) (Syntax: 'element')
WhenFalse:
null
NextVariables(0)
IReturnOperation (OperationKind.YieldBreak, Type: null, IsImplicit) (Syntax: '{ ... }')
ReturnedValue:
null
IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '{ ... }')
IForEachLoopOperation (LoopKind.ForEach) (OperationKind.Loop, Type: null) (Syntax: 'foreach (va ... rn element;')
Locals: Local_1: T element
LoopControlVariable:
IVariableDeclaratorOperation (Symbol: T element) (OperationKind.VariableDeclarator, Type: null) (Syntax: 'var')
Initializer:
null
Collection:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Collections.Generic.IEnumerable<T>, IsImplicit) (Syntax: 'source')
Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
IParameterReferenceOperation: source (OperationKind.ParameterReference, Type: System.Collections.Generic.IEnumerable<T>) (Syntax: 'source')
Body:
IConditionalOperation (OperationKind.Conditional, Type: null) (Syntax: 'if (predica ... rn element;')
Condition:
IInvocationOperation (virtual System.Boolean System.Func<T, System.Boolean>.Invoke(T arg)) (OperationKind.Invocation, Type: System.Boolean) (Syntax: 'predicate(element)')
Instance Receiver:
IParameterReferenceOperation: predicate (OperationKind.ParameterReference, Type: System.Func<T, System.Boolean>) (Syntax: 'predicate')
Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: arg) (OperationKind.Argument, Type: null) (Syntax: 'element')
ILocalReferenceOperation: element (OperationKind.LocalReference, Type: T) (Syntax: 'element')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
WhenTrue:
IReturnOperation (OperationKind.YieldReturn, Type: null) (Syntax: 'yield return element;')
ReturnedValue:
ILocalReferenceOperation: element (OperationKind.LocalReference, Type: T) (Syntax: 'element')
WhenFalse:
null
NextVariables(0)
IReturnOperation (OperationKind.YieldBreak, Type: null, IsImplicit) (Syntax: '{ ... }')
ReturnedValue:
null
"
;
var
expectedDiagnostics
=
DiagnosticDescription
.
None
;
...
...
src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs
浏览文件 @
3efd039e
...
...
@@ -5947,28 +5947,23 @@ internal abstract partial class BaseLocalFunctionStatement : Operation, ILocalFu
/// Local function symbol.
/// </summary>
public
IMethodSymbol
Symbol
{
get
;
}
protected
abstract
IBlockOperation
BlockBodyImpl
{
get
;
}
protected
abstract
IBlockOperation
ExpressionBodyImpl
{
get
;
}
public
override
IEnumerable
<
IOperation
>
Children
{
get
{
if
(
B
lockB
ody
!=
null
)
if
(
Body
!=
null
)
{
yield
return
B
lockB
ody
;
yield
return
Body
;
}
if
(
Expression
Body
!=
null
)
if
(
Ignored
Body
!=
null
)
{
yield
return
Expression
Body
;
yield
return
Ignored
Body
;
}
}
}
/// <summary>
/// Body of the local function.
/// </summary>
public
IBlockOperation
Body
=>
BlockBody
??
ExpressionBody
;
public
IBlockOperation
BlockBody
=>
Operation
.
SetParentOperation
(
BlockBodyImpl
,
this
);
public
IBlockOperation
ExpressionBody
=>
Operation
.
SetParentOperation
(
ExpressionBodyImpl
,
this
);
public
abstract
IBlockOperation
Body
{
get
;
}
public
abstract
IBlockOperation
IgnoredBody
{
get
;
}
public
override
void
Accept
(
OperationVisitor
visitor
)
{
visitor
.
VisitLocalFunction
(
this
);
...
...
@@ -5984,15 +5979,15 @@ public override void Accept(OperationVisitor visitor)
/// </summary>
internal
sealed
partial
class
LocalFunctionStatement
:
BaseLocalFunctionStatement
,
ILocalFunctionOperation
{
public
LocalFunctionStatement
(
IMethodSymbol
symbol
,
IBlockOperation
b
lockBody
,
IBlockOperation
expression
Body
,
SemanticModel
semanticModel
,
SyntaxNode
syntax
,
ITypeSymbol
type
,
Optional
<
object
>
constantValue
,
bool
isImplicit
)
:
public
LocalFunctionStatement
(
IMethodSymbol
symbol
,
IBlockOperation
b
ody
,
IBlockOperation
ignored
Body
,
SemanticModel
semanticModel
,
SyntaxNode
syntax
,
ITypeSymbol
type
,
Optional
<
object
>
constantValue
,
bool
isImplicit
)
:
base
(
symbol
,
semanticModel
,
syntax
,
type
,
constantValue
,
isImplicit
)
{
B
lockBodyImpl
=
blockBody
;
ExpressionBodyImpl
=
expressionBody
;
B
ody
=
SetParentOperation
<
IBlockOperation
>(
body
,
this
)
;
IgnoredBody
=
SetParentOperation
<
IBlockOperation
>(
ignoredBody
,
this
)
;
}
p
rotected
override
IBlockOperation
BlockBodyImpl
{
get
;
}
p
rotected
override
IBlockOperation
ExpressionBodyImpl
{
get
;
}
p
ublic
override
IBlockOperation
Body
{
get
;
}
p
ublic
override
IBlockOperation
IgnoredBody
{
get
;
}
}
/// <summary>
...
...
@@ -6000,18 +5995,18 @@ internal sealed partial class LocalFunctionStatement : BaseLocalFunctionStatemen
/// </summary>
internal
sealed
partial
class
LazyLocalFunctionStatement
:
BaseLocalFunctionStatement
,
ILocalFunctionOperation
{
private
readonly
Lazy
<
IBlockOperation
>
_lazyB
lockB
ody
;
private
readonly
Lazy
<
IBlockOperation
>
_lazy
Expression
Body
;
private
readonly
Lazy
<
IBlockOperation
>
_lazyBody
;
private
readonly
Lazy
<
IBlockOperation
>
_lazy
Ignored
Body
;
public
LazyLocalFunctionStatement
(
IMethodSymbol
symbol
,
Lazy
<
IBlockOperation
>
b
lockBody
,
Lazy
<
IBlockOperation
>
expression
Body
,
SemanticModel
semanticModel
,
SyntaxNode
syntax
,
ITypeSymbol
type
,
Optional
<
object
>
constantValue
,
bool
isImplicit
)
public
LazyLocalFunctionStatement
(
IMethodSymbol
symbol
,
Lazy
<
IBlockOperation
>
b
ody
,
Lazy
<
IBlockOperation
>
ignored
Body
,
SemanticModel
semanticModel
,
SyntaxNode
syntax
,
ITypeSymbol
type
,
Optional
<
object
>
constantValue
,
bool
isImplicit
)
:
base
(
symbol
,
semanticModel
,
syntax
,
type
,
constantValue
,
isImplicit
)
{
_lazyB
lockBody
=
blockBody
??
throw
new
System
.
ArgumentNullException
(
nameof
(
blockB
ody
));
_lazy
ExpressionBody
=
expressionBody
??
throw
new
System
.
ArgumentNullException
(
nameof
(
expression
Body
));
_lazyB
ody
=
body
??
throw
new
System
.
ArgumentNullException
(
nameof
(
b
ody
));
_lazy
IgnoredBody
=
ignoredBody
??
throw
new
System
.
ArgumentNullException
(
nameof
(
ignored
Body
));
}
p
rotected
override
IBlockOperation
BlockBodyImpl
=>
_lazyBlockBody
.
Value
;
p
rotected
override
IBlockOperation
ExpressionBodyImpl
=>
_lazyExpressionBody
.
Value
;
p
ublic
override
IBlockOperation
Body
=>
SetParentOperation
(
_lazyBody
.
Value
,
this
)
;
p
ublic
override
IBlockOperation
IgnoredBody
=>
SetParentOperation
(
_lazyIgnoredBody
.
Value
,
this
)
;
}
/// <summary>
...
...
src/Compilers/Core/Portable/Operations/ILocalFunctionOperation.cs
浏览文件 @
3efd039e
...
...
@@ -22,19 +22,14 @@ public interface ILocalFunctionOperation : IOperation
/// <summary>
/// Body of the local function.
/// </summary>
/// <remarks>
/// This will return the <see cref="BlockBody"/> if it exists, and the <see cref="ExpressionBody"/> if the <see cref="BlockBody"/> does not exist.
/// If both exist, this will return just the <see cref="BlockBody"/>, and you must use <see cref="ExpressionBody"/> to retrieve the expression body.
/// </remarks>
IBlockOperation
Body
{
get
;
}
/// <summary>
/// The block body of the local function, if it exists.
/// </summary>
IBlockOperation
BlockBody
{
get
;
}
/// <summary>
/// The expression body of the local function, if it exists.
/// An extra body for the local function, if both a block body and expression body are specified in source.
/// </summary>
IBlockOperation
ExpressionBody
{
get
;
}
/// <remarks>
/// This is only ever non-null in error situations.
/// </remarks>
IBlockOperation
IgnoredBody
{
get
;
}
}
}
src/Compilers/Core/Portable/Operations/OperationCloner.cs
浏览文件 @
3efd039e
...
...
@@ -438,7 +438,7 @@ public override IOperation VisitInvalid(IInvalidOperation operation, object argu
public
override
IOperation
VisitLocalFunction
(
ILocalFunctionOperation
operation
,
object
argument
)
{
return
new
LocalFunctionStatement
(
operation
.
Symbol
,
Visit
(
operation
.
B
lockBody
),
Visit
(
operation
.
Expression
Body
),
((
Operation
)
operation
).
SemanticModel
,
operation
.
Syntax
,
operation
.
Type
,
operation
.
ConstantValue
,
operation
.
IsImplicit
);
return
new
LocalFunctionStatement
(
operation
.
Symbol
,
Visit
(
operation
.
B
ody
),
Visit
(
operation
.
Ignored
Body
),
((
Operation
)
operation
).
SemanticModel
,
operation
.
Syntax
,
operation
.
Type
,
operation
.
ConstantValue
,
operation
.
IsImplicit
);
}
public
override
IOperation
VisitInterpolatedString
(
IInterpolatedStringOperation
operation
,
object
argument
)
...
...
src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
浏览文件 @
3efd039e
...
...
@@ -16,8 +16,7 @@ Microsoft.CodeAnalysis.OperationKind.TupleBinaryOperator = 87 -> Microsoft.CodeA
Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation
Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation.Initializer.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation.Locals.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ILocalSymbol>
Microsoft.CodeAnalysis.Operations.ILocalFunctionOperation.BlockBody.get -> Microsoft.CodeAnalysis.Operations.IBlockOperation
Microsoft.CodeAnalysis.Operations.ILocalFunctionOperation.ExpressionBody.get -> Microsoft.CodeAnalysis.Operations.IBlockOperation
Microsoft.CodeAnalysis.Operations.ILocalFunctionOperation.IgnoredBody.get -> Microsoft.CodeAnalysis.Operations.IBlockOperation
Microsoft.CodeAnalysis.Operations.IMethodBodyBaseOperation
Microsoft.CodeAnalysis.Operations.IMethodBodyBaseOperation.BlockBody.get -> Microsoft.CodeAnalysis.Operations.IBlockOperation
Microsoft.CodeAnalysis.Operations.IMethodBodyBaseOperation.ExpressionBody.get -> Microsoft.CodeAnalysis.Operations.IBlockOperation
...
...
src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs
浏览文件 @
3efd039e
...
...
@@ -1423,13 +1423,18 @@ public override void VisitLocalFunction(ILocalFunctionOperation operation)
LogString
(
")"
);
LogCommonPropertiesAndNewLine
(
operation
);
if
(
operation
.
B
lockB
ody
!=
null
)
if
(
operation
.
Body
!=
null
)
{
Visit
(
operation
.
BlockBody
,
"Block Body"
);
}
if
(
operation
.
ExpressionBody
!=
null
)
{
Visit
(
operation
.
ExpressionBody
,
"Expression Body"
);
if
(
operation
.
IgnoredBody
!=
null
)
{
Visit
(
operation
.
Body
,
"Body"
);
Visit
(
operation
.
IgnoredBody
,
"IgnoredBody"
);
}
else
{
Visit
(
operation
.
Body
);
}
}
}
...
...
src/Test/Utilities/Portable/Compilation/TestOperationVisitor.cs
浏览文件 @
3efd039e
...
...
@@ -717,29 +717,21 @@ public override void VisitLocalFunction(ILocalFunctionOperation operation)
if
(
operation
.
Body
!=
null
)
{
if
(
operation
.
BlockBody
==
null
)
var
children
=
operation
.
Children
.
ToImmutableArray
();
Assert
.
Same
(
operation
.
Body
,
children
[
0
]);
if
(
operation
.
IgnoredBody
!=
null
)
{
Assert
.
Same
(
operation
.
ExpressionBody
,
operation
.
Body
);
Assert
.
Same
(
operation
.
ExpressionBody
,
operation
.
Children
.
Single
()
);
Assert
.
Same
(
operation
.
IgnoredBody
,
children
[
1
]
);
Assert
.
Equal
(
2
,
children
.
Length
);
}
else
{
Assert
.
Same
(
operation
.
BlockBody
,
operation
.
Body
);
if
(
operation
.
ExpressionBody
!=
null
)
{
ImmutableArray
<
IOperation
>
children
=
operation
.
Children
.
ToImmutableArray
();
Assert
.
Equal
(
2
,
children
.
Length
);
Assert
.
Same
(
operation
.
BlockBody
,
children
[
0
]);
Assert
.
Same
(
operation
.
ExpressionBody
,
children
[
1
]);
}
else
{
Assert
.
Same
(
operation
.
BlockBody
,
operation
.
Children
.
Single
());
}
Assert
.
Equal
(
1
,
children
.
Length
);
}
}
else
{
Assert
.
Null
(
operation
.
IgnoredBody
);
Assert
.
Empty
(
operation
.
Children
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录