Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
1754aa4e
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,发现更多精彩内容 >>
未验证
提交
1754aa4e
编写于
1月 22, 2019
作者:
F
Fred Silberberg
提交者:
GitHub
1月 22, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #32225 from 333fred/null-coalese-assignment-support
Add support for ??= to NullableWalker
上级
8c24e04b
77fc0e4e
变更
2
展开全部
隐藏空白更改
内联
并排
Showing
2 changed file
with
789 addition
and
234 deletion
+789
-234
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+67
-28
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
...rp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+722
-206
未找到文件。
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
浏览文件 @
1754aa4e
...
...
@@ -1932,12 +1932,39 @@ private static BoundExpression SkipReferenceConversions(BoundExpression possibly
return
possiblyConversion
;
}
// https://github.com/dotnet/roslyn/issues/30140: Track nullable state from ??=.
public
override
BoundNode
VisitNullCoalescingAssignmentOperator
(
BoundNullCoalescingAssignmentOperator
node
)
{
var
result
=
base
.
VisitNullCoalescingAssignmentOperator
(
node
);
SetResult
(
node
);
return
result
;
BoundExpression
leftOperand
=
node
.
LeftOperand
;
BoundExpression
rightOperand
=
node
.
RightOperand
;
int
leftSlot
=
MakeSlot
(
leftOperand
);
// The assignment to the left below needs the declared type from VisitLvalue, but the hidden
// unnecessary check diagnostic needs the current adjusted type of the slot
VisitLvalue
(
leftOperand
);
TypeSymbolWithAnnotations
targetType
=
_resultType
;
TypeSymbolWithAnnotations
currentLeftType
=
GetAdjustedResult
(
targetType
,
leftSlot
);
if
(
currentLeftType
.
ValueCanBeNull
()
==
false
)
{
ReportNonSafetyDiagnostic
(
ErrorCode
.
HDN_ExpressionIsProbablyNeverNull
,
leftOperand
.
Syntax
);
}
var
leftState
=
this
.
State
.
Clone
();
TypeSymbolWithAnnotations
rightResult
=
VisitOptionalImplicitConversion
(
rightOperand
,
targetType
,
UseLegacyWarnings
(
leftOperand
),
AssignmentKind
.
Assignment
);
TrackNullableStateForAssignment
(
rightOperand
,
targetType
,
leftSlot
,
rightResult
,
MakeSlot
(
rightOperand
));
Join
(
ref
this
.
State
,
ref
leftState
);
TypeSymbolWithAnnotations
resultType
=
GetNullCoalescingResultType
(
leftOperand
,
currentLeftType
,
rightOperand
,
rightResult
,
targetType
.
TypeSymbol
);
_resultType
=
resultType
;
if
(
leftSlot
>
0
)
{
this
.
State
[
leftSlot
]
=
resultType
.
NullableAnnotation
;
}
return
null
;
}
public
override
BoundNode
VisitNullCoalescingOperator
(
BoundNullCoalescingOperator
node
)
...
...
@@ -2002,20 +2029,7 @@ public override BoundNode VisitNullCoalescingOperator(BoundNullCoalescingOperato
throw
ExceptionUtilities
.
UnexpectedValue
(
node
.
OperatorResultKind
);
}
NullableAnnotation
resultNullableAnnotation
;
// We want to check if the value can be nullable based on annotations and getValueNullableAnnotation might
// adjust the value that it returns to emphasize the fact. However, we want the original annotation to flow through the system.
if
(
getValueNullableAnnotation
(
leftOperand
,
leftResult
).
IsAnyNotNullable
())
{
resultNullableAnnotation
=
getNullableAnnotation
(
leftOperand
,
leftResult
);
}
else
{
resultNullableAnnotation
=
getNullableAnnotation
(
rightOperand
,
rightResult
);
}
_resultType
=
TypeSymbolWithAnnotations
.
Create
(
resultType
,
resultNullableAnnotation
);
_resultType
=
GetNullCoalescingResultType
(
leftOperand
,
leftResult
,
rightOperand
,
rightResult
,
resultType
);
return
null
;
NullableAnnotation
getNullableAnnotation
(
BoundExpression
e
,
TypeSymbolWithAnnotations
t
)
...
...
@@ -2028,16 +2042,6 @@ NullableAnnotation getNullableAnnotation(BoundExpression e, TypeSymbolWithAnnota
return
t
.
NullableAnnotation
;
}
NullableAnnotation
getValueNullableAnnotation
(
BoundExpression
e
,
TypeSymbolWithAnnotations
t
)
{
if
(
t
.
IsNull
)
{
return
GetNullableAnnotation
(
e
);
}
return
t
.
GetValueNullableAnnotation
();
}
TypeSymbol
getLeftResultType
(
TypeSymbol
leftType
,
TypeSymbol
rightType
)
{
// If there was an identity conversion between the two operands (in short, if there
...
...
@@ -2098,6 +2102,41 @@ private static NullableAnnotation GetNullableAnnotation(BoundExpression expr)
}
}
private
static
TypeSymbolWithAnnotations
GetNullCoalescingResultType
(
BoundExpression
leftOperand
,
TypeSymbolWithAnnotations
leftResult
,
BoundExpression
rightOperand
,
TypeSymbolWithAnnotations
rightResult
,
TypeSymbol
resultType
)
{
NullableAnnotation
resultNullableAnnotation
;
if
(
getValueNullableAnnotation
(
leftOperand
,
leftResult
).
IsAnyNotNullable
())
{
resultNullableAnnotation
=
getNullableAnnotation
(
leftOperand
,
leftResult
);
}
else
{
resultNullableAnnotation
=
getNullableAnnotation
(
rightOperand
,
rightResult
);
}
return
TypeSymbolWithAnnotations
.
Create
(
resultType
,
resultNullableAnnotation
);
NullableAnnotation
getNullableAnnotation
(
BoundExpression
e
,
TypeSymbolWithAnnotations
t
)
{
if
(
t
.
IsNull
)
{
return
GetNullableAnnotation
(
e
);
}
return
t
.
NullableAnnotation
;
}
NullableAnnotation
getValueNullableAnnotation
(
BoundExpression
e
,
TypeSymbolWithAnnotations
t
)
{
if
(
t
.
IsNull
)
{
return
GetNullableAnnotation
(
e
);
}
return
t
.
GetValueNullableAnnotation
();
}
}
public
override
BoundNode
VisitConditionalAccess
(
BoundConditionalAccess
node
)
{
Debug
.
Assert
(!
IsConditionalState
);
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
浏览文件 @
1754aa4e
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录