Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
ff068c9a
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,发现更多精彩内容 >>
未验证
提交
ff068c9a
编写于
6月 14, 2017
作者:
F
Fredric Silberberg
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Delegate UnboundLambda to BoundLambda conversion to the semantic model.
上级
dfd7a70e
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
67 addition
and
13 deletion
+67
-13
src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
...pilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
+5
-1
src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
...lers/CSharp/Portable/Operations/CSharpOperationFactory.cs
+15
-11
src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILambdaExpression.cs
.../Semantic/IOperation/IOperationTests_ILambdaExpression.cs
+47
-1
未找到文件。
src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
浏览文件 @
ff068c9a
...
...
@@ -51,7 +51,7 @@ protected MemberSemanticModel(CSharpCompilation compilation, CSharpSyntaxNode ro
_parentSemanticModelOpt
=
parentSemanticModelOpt
;
_speculatedPosition
=
speculatedPosition
;
_operationFactory
=
new
CSharpOperationFactory
();
_operationFactory
=
new
CSharpOperationFactory
(
this
);
}
public
override
CSharpCompilation
Compilation
...
...
@@ -983,6 +983,10 @@ internal override IOperation GetOperationWorker(CSharpSyntaxNode node, GetOperat
break
;
}
// The CSharp operation factory assumes that UnboundLambda will be bound for error recovery and never be passed to the factory
// as the start of a tree to get operations for. This is guaranteed by the builder that populates the node map, as it will call
// UnboundLambda.BindForErrorRecovery() when it encounters an UnboundLambda node.
Debug
.
Assert
(
result
.
Kind
!=
BoundKind
.
UnboundLambda
);
return
_operationFactory
.
Create
(
result
);
}
...
...
src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs
浏览文件 @
ff068c9a
...
...
@@ -3,6 +3,7 @@
using
System
;
using
System.Collections.Concurrent
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Linq
;
using
Microsoft.CodeAnalysis.CSharp
;
using
Microsoft.CodeAnalysis.CSharp.Symbols
;
...
...
@@ -13,6 +14,12 @@ internal sealed partial class CSharpOperationFactory
{
private
readonly
ConcurrentDictionary
<
BoundNode
,
IOperation
>
_cache
=
new
ConcurrentDictionary
<
BoundNode
,
IOperation
>(
concurrencyLevel
:
2
,
capacity
:
10
);
private
readonly
SemanticModel
_semanticModel
;
public
CSharpOperationFactory
(
SemanticModel
semanticModel
)
{
_semanticModel
=
semanticModel
;
}
public
IOperation
Create
(
BoundNode
boundNode
)
{
...
...
@@ -353,18 +360,15 @@ private IObjectCreationExpression CreateBoundObjectCreationExpressionOperation(B
return
new
LazyObjectCreationExpression
(
constructor
,
memberInitializers
,
argumentsInEvaluationOrder
,
isInvalid
,
syntax
,
type
,
constantValue
);
}
private
I
LambdaExpress
ion
CreateUnboundLambdaOperation
(
UnboundLambda
unboundLambda
)
private
I
Operat
ion
CreateUnboundLambdaOperation
(
UnboundLambda
unboundLambda
)
{
bool
isInvalid
=
unboundLambda
.
HasErrors
;
SyntaxNode
syntax
=
unboundLambda
.
Syntax
;
// This matches the SemanticModel implementation. This is because in VB, lambdas by themselves
// do not have a type. To get the type of a lambda expression in the SemanticModel, you need to look at
// TypeInfo.ConvertedType, rather than TypeInfo.Type. We replicate that behavior here. To get the type of
// an IUnboundLambdaExpression, you need to look at the parent IConversionExpression.
ITypeSymbol
type
=
null
;
Optional
<
object
>
constantValue
=
ConvertToOptional
(
unboundLambda
.
ConstantValue
);
Lazy
<
ILambdaExpression
>
internalLambda
=
new
Lazy
<
ILambdaExpression
>(()
=>
CreateBoundLambdaOperation
(
unboundLambda
.
BindForErrorRecovery
()));
return
new
LazyLambdaFromUnboundLambdaExpression
(
internalLambda
,
isInvalid
,
syntax
,
type
,
constantValue
);
// We want to ensure that we never see the UnboundLambda node, and that we don't end up having two different IOperation
// nodes for the lambda expression. So, we ask the semantic model for the IOperation node for the unbound lambda syntax.
// We are counting on the fact that will do the error recovery and actually create the BoundLambda node appropriate for
// this syntax node.
var
lambdaOperation
=
_semanticModel
.
GetOperationInternal
(
unboundLambda
.
Syntax
);
Debug
.
Assert
(
lambdaOperation
.
Kind
==
OperationKind
.
LambdaExpression
);
return
lambdaOperation
;
}
private
ILambdaExpression
CreateBoundLambdaOperation
(
BoundLambda
boundLambda
)
...
...
src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILambdaExpression.cs
浏览文件 @
ff068c9a
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
System.Linq
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.Semantics
;
using
Microsoft.CodeAnalysis.Test.Utilities
;
using
Xunit
;
...
...
@@ -112,5 +114,49 @@ static void F()
VerifyOperationTreeAndDiagnosticsForTest
<
EqualsValueClauseSyntax
>(
source
,
expectedOperationTree
,
expectedDiagnostics
);
}
[
Fact
]
public
void
ILambdaExpression_UnboundLambda_ReferenceEquality
()
{
string
source
=
@"
using System;
class Program
{
static void Main(string[] args)
{
var x /*<bind>*/= () => F()/*</bind>*/;
}
static void F()
{
}
}
"
;
var
compilation
=
CreateCompilationWithMscorlibAndSystemCore
(
source
);
var
syntaxTree
=
compilation
.
SyntaxTrees
[
0
];
var
semanticModel
=
compilation
.
GetSemanticModel
(
syntaxTree
);
var
variableDeclaration
=
syntaxTree
.
GetRoot
().
DescendantNodes
().
OfType
<
VariableDeclarationSyntax
>().
Single
();
var
lambdaSyntax
=
(
LambdaExpressionSyntax
)
variableDeclaration
.
Variables
.
Single
().
Initializer
.
Value
;
var
variableDeclarationOperation
=
(
IVariableDeclarationStatement
)
semanticModel
.
GetOperationInternal
(
variableDeclaration
);
var
variableTreeLambdaOperation
=
(
ILambdaExpression
)
variableDeclarationOperation
.
Declarations
.
Single
().
Initializer
;
var
lambdaOperation
=
(
ILambdaExpression
)
semanticModel
.
GetOperationInternal
(
lambdaSyntax
);
// Assert that both ways of getting to the lambda (requesting the lambda directly, and requesting via the lambda syntax)
// return the same bound node.
Assert
.
Same
(
variableTreeLambdaOperation
,
lambdaOperation
);
var
variableDeclarationOperationSecondRequest
=
(
IVariableDeclarationStatement
)
semanticModel
.
GetOperationInternal
(
variableDeclaration
);
var
variableTreeLambdaOperationSecondRequest
=
(
ILambdaExpression
)
variableDeclarationOperation
.
Declarations
.
Single
().
Initializer
;
var
lambdaOperationSecondRequest
=
(
ILambdaExpression
)
semanticModel
.
GetOperationInternal
(
lambdaSyntax
);
// Assert that, when request the variable declaration or the lambda for a second time, there is no rebinding of the
// underlying UnboundLambda, and we get the same ILambdaExpression as before
Assert
.
Same
(
variableTreeLambdaOperation
,
variableTreeLambdaOperationSecondRequest
);
Assert
.
Same
(
lambdaOperation
,
lambdaOperationSecondRequest
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录