Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
30d5cfd6
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,发现更多精彩内容 >>
未验证
提交
30d5cfd6
编写于
2月 11, 2020
作者:
J
Julien Couvreur
提交者:
GitHub
2月 11, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Analyze comparison with boolean constants (#41349)
上级
961f2610
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
478 addition
and
73 deletion
+478
-73
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
+68
-5
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
...rp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+345
-68
src/Compilers/CSharp/Test/Semantic/Semantics/SlowTests.cs
src/Compilers/CSharp/Test/Semantic/Semantics/SlowTests.cs
+65
-0
未找到文件。
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
浏览文件 @
30d5cfd6
...
...
@@ -2750,22 +2750,86 @@ protected override void VisitBinaryOperatorChildren(ArrayBuilder<BoundBinaryOper
var
binary
=
stack
.
Pop
();
var
(
leftOperand
,
leftConversion
)
=
RemoveConversion
(
binary
.
Left
,
includeExplicitConversions
:
false
);
Visit
Rvalue
(
leftOperand
);
Visit
(
leftOperand
);
while
(
true
)
{
AfterLeftChildHasBeenVisited
(
leftOperand
,
leftConversion
,
binary
);
if
(!
learnFromBooleanConstantTest
())
{
Unsplit
();
// VisitRvalue does this
UseRvalueOnly
(
leftOperand
);
// drop lvalue part
AfterLeftChildHasBeenVisited
(
leftOperand
,
leftConversion
,
binary
);
}
if
(
stack
.
Count
==
0
)
{
break
;
}
Unsplit
();
// VisitRvalue does this
leftOperand
=
binary
;
leftConversion
=
Conversion
.
Identity
;
binary
=
stack
.
Pop
();
}
// learn from true/false constant
bool
learnFromBooleanConstantTest
()
{
if
(!
IsConditionalState
)
{
return
false
;
}
if
(!
leftConversion
.
IsIdentity
)
{
return
false
;
}
BinaryOperatorKind
op
=
binary
.
OperatorKind
.
Operator
();
if
(
op
!=
BinaryOperatorKind
.
Equal
&&
op
!=
BinaryOperatorKind
.
NotEqual
)
{
return
false
;
}
bool
isSense
;
if
(
binary
.
Right
.
ConstantValue
?.
IsBoolean
==
true
)
{
UseRvalueOnly
(
leftOperand
);
// record result for the left
var
stateWhenTrue
=
this
.
StateWhenTrue
.
Clone
();
var
stateWhenFalse
=
this
.
StateWhenFalse
.
Clone
();
Unsplit
();
Visit
(
binary
.
Right
);
UseRvalueOnly
(
binary
.
Right
);
// record result for the right
SetConditionalState
(
stateWhenTrue
,
stateWhenFalse
);
isSense
=
(
op
==
BinaryOperatorKind
.
Equal
)
==
binary
.
Right
.
ConstantValue
.
BooleanValue
;
}
else
if
(
binary
.
Left
.
ConstantValue
?.
IsBoolean
==
true
)
{
Unsplit
();
UseRvalueOnly
(
leftOperand
);
// record result for the left
Visit
(
binary
.
Right
);
UseRvalueOnly
(
binary
.
Right
);
// record result for the right
isSense
=
(
op
==
BinaryOperatorKind
.
Equal
)
==
binary
.
Left
.
ConstantValue
.
BooleanValue
;
}
else
{
return
false
;
}
if
(!
isSense
&&
IsConditionalState
)
{
SetConditionalState
(
StateWhenFalse
,
StateWhenTrue
);
}
// record result for the binary
Debug
.
Assert
(
binary
.
Type
.
SpecialType
==
SpecialType
.
System_Boolean
);
SetResult
(
binary
,
TypeWithState
.
ForType
(
binary
.
Type
),
TypeWithAnnotations
.
Create
(
binary
.
Type
));
return
true
;
}
}
private
void
AfterLeftChildHasBeenVisited
(
BoundExpression
leftOperand
,
Conversion
leftConversion
,
BoundBinaryOperator
binary
)
...
...
@@ -2863,11 +2927,10 @@ private void AfterLeftChildHasBeenVisited(BoundExpression leftOperand, Conversio
BinaryOperatorKind
op
=
binary
.
OperatorKind
.
Operator
();
// learn from null constant
if
(
op
==
BinaryOperatorKind
.
Equal
||
op
==
BinaryOperatorKind
.
NotEqual
)
{
// learn from null constant
BoundExpression
operandComparedToNull
=
null
;
if
(
binary
.
Right
.
ConstantValue
?.
IsNull
==
true
)
{
operandComparedToNull
=
binary
.
Left
;
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
浏览文件 @
30d5cfd6
...
...
@@ -21990,7 +21990,7 @@ public void Main()
);
}
[Fact]
[Fact
, WorkItem(29855, "https://github.com/dotnet/roslyn/issues/29855")
]
public void MaybeNullWhenTrue_EqualsTrue()
{
var c = CreateCompilation(new[] { @"
...
...
@@ -22014,14 +22014,352 @@ public void Main(string s)
}
", MaybeNullWhenAttributeDefinition }, options: WithNonNullTypesTrue());
// https://github.com/dotnet/roslyn/issues/29855: there should only be one diagnostic
c.VerifyDiagnostics(
// (9,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // warn
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13)
);
}
[Fact, WorkItem(29855, "https://github.com/dotnet/roslyn/issues/29855")]
public void IsNullEqualsTrue()
{
var c = CreateNullableCompilation(@"
class C
{
void M(string s)
{
if ((s is null) == true)
s.ToString(); // 1
else
s.ToString();
}
void M2(string s)
{
if (true == (s is null))
s.ToString(); // 2
else
s.ToString();
}
}
");
c.VerifyDiagnostics(
// (7,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 13),
// (15,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(15, 13)
);
}
[Fact, WorkItem(29855, "https://github.com/dotnet/roslyn/issues/29855")]
public void IsNullEqualsTrueEqualsFalse()
{
var c = CreateNullableCompilation(@"
class C
{
void M(string s)
{
if (((s is null) == true) == false)
s.ToString();
else
s.ToString(); // 1
}
void M2(string s)
{
if (false == (true == (s is null)))
s.ToString();
else
s.ToString(); // 2
}
}
");
c.VerifyDiagnostics(
// (9,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13),
// (17,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(17, 13)
);
}
[Fact, WorkItem(29855, "https://github.com/dotnet/roslyn/issues/29855")]
public void IsNullEqualsFalse()
{
var c = CreateNullableCompilation(@"
class C
{
void M(string s)
{
if ((s is null) == false)
s.ToString();
else
s.ToString(); // 1
}
void M2(string s)
{
if (false == (s is null))
s.ToString();
else
s.ToString(); // 2
}
}
");
c.VerifyDiagnostics(
// (9,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13),
// (17,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(17, 13)
);
}
[Fact, WorkItem(29855, "https://github.com/dotnet/roslyn/issues/29855")]
public void IsNullNotEqualsTrue()
{
var c = CreateNullableCompilation(@"
class C
{
void M(string s)
{
if ((s is null) != true)
s.ToString();
else
s.ToString(); // 1
}
void M2(string s)
{
if (true != (s is null))
s.ToString();
else
s.ToString(); // 2
}
}
");
c.VerifyDiagnostics(
// (9,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13),
// (17,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(17, 13)
);
}
[Fact, WorkItem(29855, "https://github.com/dotnet/roslyn/issues/29855")]
public void IsNullNotEqualsFalse()
{
var c = CreateNullableCompilation(@"
class C
{
void M(string s)
{
if ((s is null) != false)
s.ToString(); // 1
else
s.ToString();
}
void M2(string s)
{
if (false != (s is null))
s.ToString(); // 2
else
s.ToString();
}
}
");
c.VerifyDiagnostics(
// (7,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 13),
// (15,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(15, 13)
);
}
[Fact, WorkItem(29855, "https://github.com/dotnet/roslyn/issues/29855")]
public void OnlySwapConditionalStatesWhenInConditionalState()
{
var c = CreateNullableCompilation(@"
class C
{
void M(bool b)
{
if (b == (true != b))
{
}
}
}
");
c.VerifyDiagnostics();
}
[Fact, WorkItem(41107, "https://github.com/dotnet/roslyn/issues/41107")]
public void NullConditionalEqualsTrue()
{
var c = CreateNullableCompilation(new[] { @"
public class C
{
public C? field;
public bool value;
static public void M(C c)
{
if (c.field?.value == true)
{
c.field.ToString();
}
else
{
c.field.ToString(); // 1
}
}
static public void M2(C c)
{
if (false == c.field?.value)
{
c.field.ToString();
}
else
{
c.field.ToString(); // 2
}
}
}
", NotNullWhenAttributeDefinition });
c.VerifyDiagnostics(
// (15,13): warning CS8602: Dereference of a possibly null reference.
// c.field.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.field").WithLocation(15, 13),
// (27,13): warning CS8602: Dereference of a possibly null reference.
// c.field.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.field").WithLocation(27, 13)
);
}
[Fact, WorkItem(41107, "https://github.com/dotnet/roslyn/issues/41107")]
public void EqualsComplicatedTrue()
{
var c = CreateNullableCompilation(new[] { @"
public class C
{
public C? field;
public bool value;
static C? MaybeNull() => throw null!;
static public void M(C c)
{
if ((c.field is null) == (true || MaybeNull()?.value == true))
{
c.field.ToString(); // 1
}
else
{
c.field.ToString(); // 2
}
}
static public void M2(C c)
{
if ((false && MaybeNull()?.value == true) == (c.field is null))
{
c.field.ToString(); // 3
}
else
{
c.field.ToString(); // 4
}
}
}
", NotNullWhenAttributeDefinition });
c.VerifyDiagnostics(
// (13,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // ok
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13)
// c.field.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.field").WithLocation(13, 13),
// (17,13): warning CS8602: Dereference of a possibly null reference.
// c.field.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.field").WithLocation(17, 13),
// (25,13): warning CS8602: Dereference of a possibly null reference.
// c.field.ToString(); // 3
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.field").WithLocation(25, 13),
// (29,13): warning CS8602: Dereference of a possibly null reference.
// c.field.ToString(); // 4
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.field").WithLocation(29, 13)
);
}
[Fact, WorkItem(41107, "https://github.com/dotnet/roslyn/issues/41107")]
public void NullConditionalWithExtensionMethodEqualsTrue()
{
var c = CreateNullableCompilation(new[] { @"
using System.Diagnostics.CodeAnalysis;
public class C
{
public C? field;
static public void M(C c)
{
if (c.field?.field.IsKind() == true)
{
c.field.field.ToString(); // 1
}
}
static public void M2(C c)
{
if (true == c.field?.field.IsKind())
{
c.field.field.ToString(); // 2
}
}
static public void M3(C c)
{
if (Extension.IsKind(c.field?.field) == true)
{
c.field.field.ToString();
}
}
}
public static class Extension
{
public static bool IsKind([NotNullWhen(true)] this C? c)
{
throw null!;
}
}
", NotNullWhenAttributeDefinition });
// Note: when we're done analyzing `c.field?.field.IsKind()` we have an unconditional state.
// If we wanted to analyze this properly, we would probably need a WhenTrue/WhenFalse/WhenNull split.
c.VerifyDiagnostics(
// (12,13): warning CS8602: Dereference of a possibly null reference.
// c.field.field.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.field.field").WithLocation(12, 13),
// (20,13): warning CS8602: Dereference of a possibly null reference.
// c.field.field.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.field.field").WithLocation(20, 13)
);
}
...
...
@@ -22480,14 +22818,10 @@ public void Main(string? s)
}
", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue());
// https://github.com/dotnet/roslyn/issues/29855: there should only be one diagnostic
c.VerifyDiagnostics(
// (9,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // warn
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13),
// (13,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // ok
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13)
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13)
);
}
...
...
@@ -22610,11 +22944,7 @@ public void Main(string? s)
}
", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue());
// https://github.com/dotnet/roslyn/issues/29855: there should only be one diagnostic
c.VerifyDiagnostics(
// (9,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // ok
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13),
// (13,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // warn
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13)
...
...
@@ -22646,14 +22976,10 @@ public void Main(string? s)
}
", NotNullWhenAttributeDefinition }, options: WithNonNullTypesTrue());
// https://github.com/dotnet/roslyn/issues/29855: there should only be one diagnostic
c.VerifyDiagnostics(
// (9,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // warn
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13),
// (13,13): warning CS8602: Dereference of a possibly null reference.
// s.ToString(); // ok
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(13, 13)
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 13)
);
}
...
...
@@ -27880,6 +28206,7 @@ void M(string? s1)
}
[Fact]
public void NotNull_ConditionalMethodInReleaseMode()
{
CSharpCompilation c = CreateCompilation(new[] { @"
...
...
@@ -35219,56 +35546,6 @@ void M(C c)
comp.VerifyDiagnostics();
}
[Fact, WorkItem(35949, "https://github.com/dotnet/roslyn/issues/35949")]
public void NotNull_Complexity()
{
var source = @"
using System;
using System.Diagnostics.CodeAnalysis;
class C
{
C f = null!;
void M(C c)
{
c.f = c;
c.NotNull(
x => x.f.NotNull(
y => y.f.NotNull(
z => z.f.NotNull(
q => q.f.NotNull(
w => w.f.NotNull(
e => e.f.NotNull(
r => r.f.NotNull(
_ =>
{
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
return """";
}))))))));
}
}
static class Ext
{
public static V NotNull<T, V>([NotNull] this T t, Func<T, V> f) => throw null!;
}
";
var comp = CreateNullableCompilation(new[] { NotNullAttributeDefinition, source });
comp.VerifyDiagnostics();
}
[Fact]
public void NotNull_OutParameter_GenericType()
{
src/Compilers/CSharp/Test/Semantic/Semantics/SlowTests.cs
0 → 100644
浏览文件 @
30d5cfd6
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using
Microsoft.CodeAnalysis.CSharp.Test.Utilities
;
using
Roslyn.Test.Utilities
;
using
Xunit
;
namespace
Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
{
public
class
SlowTests
:
CSharpTestBase
{
[
Fact
,
WorkItem
(
35949
,
"https://github.com/dotnet/roslyn/issues/35949"
)]
public
void
NotNull_Complexity
()
{
var
source
=
@"
#nullable enable
using System;
using System.Diagnostics.CodeAnalysis;
class C
{
C f = null!;
void M(C c)
{
c.f = c;
c.NotNull(
x => x.f.NotNull(
y => y.f.NotNull(
z => z.f.NotNull(
q => q.f.NotNull(
w => w.f.NotNull(
e => e.f.NotNull(
r => r.f.NotNull(
_ =>
{
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
"""".NotNull(s => s);
return """";
}))))))));
}
}
static class Ext
{
public static V NotNull<T, V>([NotNull] this T t, Func<T, V> f) => throw null!;
}
"
;
var
comp
=
CreateCompilation
(
new
[]
{
NotNullAttributeDefinition
,
source
});
comp
.
VerifyDiagnostics
();
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录