Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
06f9495f
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,发现更多精彩内容 >>
未验证
提交
06f9495f
编写于
9月 17, 2020
作者:
R
Rikki Gibson
提交者:
GitHub
9月 17, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix nullable suppression in conditional access (#47712)
上级
b8cd43a6
变更
3
展开全部
隐藏空白更改
内联
并排
Showing
3 changed file
with
935 addition
and
4 deletion
+935
-4
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
+26
-0
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
...rp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+197
-3
src/Compilers/CSharp/Test/Syntax/Parsing/SuppressNullableWarningExpressionParsingTests.cs
.../Parsing/SuppressNullableWarningExpressionParsingTests.cs
+712
-1
未找到文件。
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
浏览文件 @
06f9495f
...
...
@@ -10580,6 +10580,18 @@ internal ExpressionSyntax ParseConsequenceSyntax()
while (true)
{
tk = this.CurrentToken.Kind;
// Nullable suppression operators should only be consumed by a conditional access
// if there are further conditional operations performed after the suppression
if (isOptionalExclamationsFollowedByConditionalOperation())
{
while (tk == SyntaxKind.ExclamationToken)
{
expr = _syntaxFactory.PostfixUnaryExpression(SyntaxKind.SuppressNullableWarningExpression, expr, EatToken());
expr = CheckFeatureAvailability(expr, MessageID.IDS_FeatureNullableReferenceTypes);
tk = this.CurrentToken.Kind;
}
}
switch (tk)
{
case SyntaxKind.OpenParenToken:
...
...
@@ -10607,6 +10619,20 @@ internal ExpressionSyntax ParseConsequenceSyntax()
return expr;
}
}
bool isOptionalExclamationsFollowedByConditionalOperation()
{
var tk = this.CurrentToken.Kind;
for (int i = 1; tk == SyntaxKind.ExclamationToken; i++)
{
tk = this.PeekToken(i).Kind;
}
return tk
is SyntaxKind.OpenParenToken
or SyntaxKind.OpenBracketToken
or SyntaxKind.DotToken
or SyntaxKind.QuestionToken;
}
}
internal ArgumentListSyntax ParseParenthesizedArgumentList()
...
...
src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
浏览文件 @
06f9495f
...
...
@@ -7893,15 +7893,73 @@ public void SuppressionOnNullableReferenceType_AppliedOnField2()
public class C
{
public string? field;
void M(C? c)
void M
1
(C? c)
{
c?.field!.ToString();
c.ToString(); // We learned from suppressed dereference that `c` isn't null
c.ToString(); // 1
}
void M2(C? c)
{
c!?.field!.ToString();
c.ToString(); // 2
}
void M3(C? c)
{
_ = c?.field!.ToString()!;
c.ToString(); // 3
}
void M4(C? c)
{
(c?.field!.ToString()!).ToString();
c.ToString(); // no warning because 'c' was part of a call receiver in previous line
}
}
";
var c = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue());
c.VerifyDiagnostics();
c.VerifyDiagnostics(
// (8,9): warning CS8602: Dereference of a possibly null reference.
// c.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c", isSuppressed: false).WithLocation(8, 9),
// (14,9): warning CS8602: Dereference of a possibly null reference.
// c.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c", isSuppressed: false).WithLocation(14, 9),
// (20,9): warning CS8602: Dereference of a possibly null reference.
// c.ToString(); // 3
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c", isSuppressed: false).WithLocation(20, 9));
}
[Fact]
[WorkItem(43659, "https://github.com/dotnet/roslyn/issues/43659")]
public void SuppressionOnNullableReferenceType_AppliedOnField3()
{
var source = @"
public class C
{
public string[]? F1;
public System.Func<object>? F2;
static void M1(C? c)
{
c?.F1![0].ToString();
c.ToString(); // 1
}
static void M2(C? c)
{
c?.F2!().ToString();
c.ToString(); // 2
}
}
";
var c = CreateNullableCompilation(source);
c.VerifyDiagnostics(
// (9,9): warning CS8602: Dereference of a possibly null reference.
// c.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c", isSuppressed: false).WithLocation(9, 9),
// (14,9): warning CS8602: Dereference of a possibly null reference.
// c.ToString(); // 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c", isSuppressed: false).WithLocation(14, 9));
}
[Fact]
...
...
@@ -63580,6 +63638,142 @@ static void G(string s)
);
}
[Fact]
[WorkItem(43659, "https://github.com/dotnet/roslyn/issues/43659")]
public void SuppressNullableWarning_ConditionalAccess_01()
{
var source = @"
#nullable enable
using System;
using System.Linq;
class Program
{
static void Main()
{
int[]? a = null;
string? s1 = a?.First().ToString();
Console.Write(s1 == null);
string? s2 = a?.First()!.ToString();
Console.Write(s2 == null);
string s3 = a?.First().ToString()!;
Console.Write(s3 == null);
string? s4 = (a?.First()).ToString();
Console.Write(s4 == null);
string? s5 = (a?.First())!.ToString();
Console.Write(s5 == null);
}
}";
var comp = CreateCompilation(source, options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: "TrueTrueTrueFalseFalse");
}
[Fact]
[WorkItem(43659, "https://github.com/dotnet/roslyn/issues/43659")]
public void SuppressNullableWarning_ConditionalAccess_02()
{
var source = @"
#nullable enable
using System.Linq;
class Program
{
static void Main()
{
int[]? a = null;
string? s1 = a?.First()!!.ToString(); // 1
string? s2 = a?.First()!!!!.ToString(); // 2
}
}";
var comp = CreateCompilation(source, options: TestOptions.DebugExe);
comp.VerifyDiagnostics(
// (12,24): error CS8715: Duplicate null suppression operator ('!')
// string? s1 = a?.First()!!.ToString(); // 1
Diagnostic(ErrorCode.ERR_DuplicateNullSuppression, ".First()", isSuppressed: false).WithLocation(12, 24),
// (13,24): error CS8715: Duplicate null suppression operator ('!')
// string? s2 = a?.First()!!!!.ToString(); // 2
Diagnostic(ErrorCode.ERR_DuplicateNullSuppression, ".First()", isSuppressed: false).WithLocation(13, 24),
// (13,24): error CS8715: Duplicate null suppression operator ('!')
// string? s2 = a?.First()!!!!.ToString(); // 2
Diagnostic(ErrorCode.ERR_DuplicateNullSuppression, ".First()", isSuppressed: false).WithLocation(13, 24),
// (13,24): error CS8715: Duplicate null suppression operator ('!')
// string? s2 = a?.First()!!!!.ToString(); // 2
Diagnostic(ErrorCode.ERR_DuplicateNullSuppression, ".First()", isSuppressed: false).WithLocation(13, 24));
}
[Fact]
[WorkItem(43659, "https://github.com/dotnet/roslyn/issues/43659")]
public void SuppressNullableWarning_ConditionalAccess_03()
{
var source = @"
#nullable enable
using System;
public class D { }
public class C { public D d = null!; }
public class B { public C? c; }
public class A { public B? b; }
class Program
{
static void Main()
{
M(new A());
}
static void M(A a)
{
var str = a.b?.c!.d.ToString();
Console.Write(str == null);
}
}";
var comp = CreateCompilation(source, options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: "True");
}
[Fact]
[WorkItem(43659, "https://github.com/dotnet/roslyn/issues/43659")]
public void SuppressNullableWarning_ConditionalAccess_04()
{
var source = @"
#nullable enable
public class D { }
public class C { public D? d; }
public class B { public C? c; }
public class A { public B? b; }
class Program
{
static void M(A a)
{
string str1 = a.b?.c!.d.ToString(); // 1, 2
string str2 = a.b?.c!.d!.ToString(); // 3
string str3 = a.b?.c!.d!.ToString()!;
}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (13,23): warning CS8600: Converting null literal or possible null value to non-nullable type.
// string str1 = a.b?.c!.d.ToString(); // 1, 2
Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "a.b?.c!.d.ToString()", isSuppressed: false).WithLocation(13, 23),
// (13,27): warning CS8602: Dereference of a possibly null reference.
// string str1 = a.b?.c!.d.ToString(); // 1, 2
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, ".c!.d", isSuppressed: false).WithLocation(13, 27),
// (14,23): warning CS8600: Converting null literal or possible null value to non-nullable type.
// string str2 = a.b?.c!.d!.ToString(); // 3
Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "a.b?.c!.d!.ToString()", isSuppressed: false).WithLocation(14, 23));
}
[Fact]
public void SuppressNullableWarning_Nested()
{
src/Compilers/CSharp/Test/Syntax/Parsing/SuppressNullableWarningExpressionParsingTests.cs
浏览文件 @
06f9495f
此差异已折叠。
点击以展开。
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录