Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
ce20f709
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,发现更多精彩内容 >>
提交
ce20f709
编写于
4月 11, 2020
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add tests
上级
2ef034d5
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
718 addition
and
44 deletion
+718
-44
src/Analyzers/CSharp/Tests/UseConditionalExpression/UseConditionalExpressionForAssignmentTests.cs
...lExpression/UseConditionalExpressionForAssignmentTests.cs
+540
-0
src/Analyzers/Core/Analyzers/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentDiagnosticAnalyzer.cs
...seConditionalExpressionForAssignmentDiagnosticAnalyzer.cs
+1
-1
src/Analyzers/Core/Analyzers/UseConditionalExpression/ForAssignment/UseConditionalExpressionForAssignmentHelpers.cs
...ssignment/UseConditionalExpressionForAssignmentHelpers.cs
+50
-15
src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentCodeFixProvider.cs
...ctUseConditionalExpressionForAssignmentCodeFixProvider.cs
+56
-23
src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnCodeFixProvider.cs
...stractUseConditionalExpressionForReturnCodeFixProvider.cs
+9
-5
src/Analyzers/VisualBasic/Tests/UseConditionalExpression/UseConditionalExpressionForAssignmentTests.vb
...lExpression/UseConditionalExpressionForAssignmentTests.vb
+31
-0
src/Analyzers/VisualBasic/Tests/UseConditionalExpression/UseConditionalExpressionForReturnTests.vb
...ionalExpression/UseConditionalExpressionForReturnTests.vb
+31
-0
未找到文件。
src/Analyzers/CSharp/Tests/UseConditionalExpression/UseConditionalExpressionForAssignmentTests.cs
浏览文件 @
ce20f709
...
...
@@ -12,6 +12,7 @@
using
Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics
;
using
Microsoft.CodeAnalysis.Test.Utilities
;
using
Xunit
;
using
Roslyn.Test.Utilities
;
#if CODE_STYLE
using
Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions
;
...
...
@@ -61,6 +62,66 @@ void M(int i)
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestOnSimpleAssignment_Throw1
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M(int i)
{
[||]if (true)
{
throw new System.Exception();
}
else
{
i = 1;
}
}
}"
,
@"
class C
{
void M(int i)
{
i = true ? throw new System.Exception() : 1;
}
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestOnSimpleAssignment_Throw2
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M(int i)
{
[||]if (true)
{
i = 0;
}
else
{
throw new System.Exception();
}
}
}"
,
@"
class C
{
void M(int i)
{
i = true ? 0 : throw new System.Exception();
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestOnSimpleAssignmentNoBlocks
()
{
...
...
@@ -163,6 +224,36 @@ void M()
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestOnAssignmentToUndefinedField_Throw
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M()
{
[||]if (true)
{
this.i = 0;
}
else
{
throw new System.Exception();
}
}
}"
,
@"
class C
{
void M()
{
this.i = true ? 0 : throw new System.Exception();
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestOnNonUniformTargetSyntax
()
{
...
...
@@ -255,6 +346,68 @@ void M()
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestOnAssignmentToAboveLocalNoInitializer_Throw1
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M()
{
int i;
[||]if (true)
{
i = 0;
}
else
{
throw new System.Exception();
}
}
}"
,
@"
class C
{
void M()
{
int i = true ? 0 : throw new System.Exception();
}
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestOnAssignmentToAboveLocalNoInitializer_Throw2
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M()
{
int i;
[||]if (true)
{
throw new System.Exception();
}
else
{
i = 1;
}
}
}"
,
@"
class C
{
void M()
{
int i = true ? throw new System.Exception() : 1;
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestOnAssignmentToAboveLocalLiteralInitializer
()
{
...
...
@@ -597,6 +750,26 @@ void M(int i)
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestMissingWithoutElseWithThrowStatementAfterwards
()
{
await
TestMissingInRegularAndScriptAsync
(
@"
class C
{
void M(int i)
{
[||]if (true)
{
i = 0;
}
throw new System.Exception();
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestConversionWithUseVarForAll_CastInsertedToKeepTypeSame
()
{
...
...
@@ -629,6 +802,67 @@ void M()
}"
,
options
:
s_preferImplicitTypeAlways
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestConversionWithUseVarForAll_CastInsertedToKeepTypeSame_Throw1
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M()
{
object o;
[||]if (true)
{
throw new System.Exception();
}
else
{
o = ""b"";
}
}
}"
,
@"
class C
{
void M()
{
object o = true ? throw new System.Exception() : ""b"";
}
}"
,
options
:
s_preferImplicitTypeAlways
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestConversionWithUseVarForAll_CastInsertedToKeepTypeSame_Throw2
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M()
{
object o;
[||]if (true)
{
o = ""a"";
}
else
{
throw new System.Exception();
}
}
}"
,
@"
class C
{
void M()
{
object o = true ? ""a"" : throw new System.Exception();
}
}"
,
options
:
s_preferImplicitTypeAlways
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestConversionWithUseVarForAll_CanUseVarBecauseConditionalTypeMatches
()
{
...
...
@@ -659,6 +893,68 @@ void M()
}"
,
options
:
s_preferImplicitTypeAlways
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestConversionWithUseVarForAll_CanUseVarBecauseConditionalTypeMatches_Throw1
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M()
{
string s;
[||]if (true)
{
throw new System.Exception();
}
else
{
s = null;
}
}
}"
,
@"
class C
{
void M()
{
string s = true ? throw new System.Exception() : (string)null;
}
}"
,
options
:
s_preferImplicitTypeAlways
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestConversionWithUseVarForAll_CanUseVarBecauseConditionalTypeMatches_Throw2
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M()
{
string s;
[||]if (true)
{
s = ""a"";
}
else
{
throw new System.Exception();
}
}
}"
,
@"
class C
{
void M()
{
string s = true ? ""a"" : throw new System.Exception();
}
}"
,
options
:
s_preferImplicitTypeAlways
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestConversionWithUseVarForAll_CanUseVarButRequiresCastOfConditionalBranch
()
{
...
...
@@ -900,6 +1196,84 @@ void M(int i)
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestElseIfWithBlock_Throw1
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M(int i)
{
if (true)
{
}
else [||]if (false)
{
throw new System.Exception();
}
else
{
i = 0;
}
}
}"
,
@"
class C
{
void M(int i)
{
if (true)
{
}
else
{
i = false ? throw new System.Exception() : 0;
}
}
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestElseIfWithBlock_Throw2
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M(int i)
{
if (true)
{
}
else [||]if (false)
{
i = 1;
}
else
{
throw new System.Exception();
}
}
}"
,
@"
class C
{
void M(int i)
{
if (true)
{
}
else
{
i = false ? 1 : throw new System.Exception();
}
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestElseIfWithoutBlock
()
{
...
...
@@ -956,6 +1330,52 @@ void M(ref int i, ref int j)
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestRefAssignment1_Throw1
()
{
await
TestMissingAsync
(
@"
class C
{
void M(ref int i, ref int j)
{
ref int x = ref i;
[||]if (true)
{
throw new System.Exception();
}
else
{
x = ref j;
}
}
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestRefAssignment1_Throw2
()
{
await
TestMissingAsync
(
@"
class C
{
void M(ref int i, ref int j)
{
ref int x = ref i;
[||]if (true)
{
x = ref i;
}
else
{
throw new System.Exception();
}
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestTrueFalse1
()
{
...
...
@@ -985,6 +1405,66 @@ void M(bool i, int j)
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestTrueFalse_Throw1
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M(bool i, int j)
{
[||]if (j == 0)
{
i = true;
}
else
{
throw new System.Exception();
}
}
}"
,
@"
class C
{
void M(bool i, int j)
{
i = j == 0 ? true : throw new System.Exception();
}
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestTrueFalse_Throw2
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M(bool i, int j)
{
[||]if (j == 0)
{
throw new System.Exception();
}
else
{
i = false;
}
}
}"
,
@"
class C
{
void M(bool i, int j)
{
i = j == 0 ? throw new System.Exception() : false;
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestTrueFalse2
()
{
...
...
@@ -1011,6 +1491,66 @@ void M(bool i, int j)
{
i = j != 0;
}
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestFalseTrue_Throw1
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M(bool i, int j)
{
[||]if (j == 0)
{
throw new System.Exception();
}
else
{
i = true;
}
}
}"
,
@"
class C
{
void M(bool i, int j)
{
i = j == 0 ? throw new System.Exception() : true;
}
}"
);
}
[
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)]
public
async
Task
TestFalseTrue_Throw2
()
{
await
TestInRegularAndScriptAsync
(
@"
class C
{
void M(bool i, int j)
{
[||]if (j == 0)
{
i = false;
}
else
{
throw new System.Exception();
}
}
}"
,
@"
class C
{
void M(bool i, int j)
{
i = j == 0 ? false : throw new System.Exception();
}
}"
);
}
}
...
...
src/Analyzers/Core/Analyzers/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentDiagnosticAnalyzer.cs
浏览文件 @
ce20f709
...
...
@@ -23,6 +23,6 @@ internal abstract class AbstractUseConditionalExpressionForAssignmentDiagnosticA
protected
override
bool
TryMatchPattern
(
IConditionalOperation
ifOperation
)
=>
UseConditionalExpressionForAssignmentHelpers
.
TryMatchPattern
(
GetSyntaxFacts
(),
ifOperation
,
out
_
,
out
_
);
GetSyntaxFacts
(),
ifOperation
,
out
_
,
out
_
,
out
_
,
out
_
);
}
}
src/Analyzers/Core/Analyzers/UseConditionalExpression/ForAssignment/UseConditionalExpressionForAssignmentHelpers.cs
浏览文件 @
ce20f709
...
...
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
Microsoft.CodeAnalysis.LanguageServices
;
using
Microsoft.CodeAnalysis.Operations
;
...
...
@@ -12,11 +14,15 @@ internal static class UseConditionalExpressionForAssignmentHelpers
public
static
bool
TryMatchPattern
(
ISyntaxFacts
syntaxFacts
,
IConditionalOperation
ifOperation
,
out
ISimpleAssignmentOperation
trueAssignment
,
out
ISimpleAssignmentOperation
falseAssignment
)
out
ISimpleAssignmentOperation
?
trueAssignment
,
out
IThrowOperation
?
trueThrow
,
out
ISimpleAssignmentOperation
?
falseAssignment
,
out
IThrowOperation
?
falseThrow
)
{
trueAssignment
=
null
;
trueThrow
=
null
;
falseAssignment
=
null
;
falseThrow
=
null
;
var
trueStatement
=
ifOperation
.
WhenTrue
;
var
falseStatement
=
ifOperation
.
WhenFalse
;
...
...
@@ -24,38 +30,67 @@ internal static class UseConditionalExpressionForAssignmentHelpers
trueStatement
=
UseConditionalExpressionHelpers
.
UnwrapSingleStatementBlock
(
trueStatement
);
falseStatement
=
UseConditionalExpressionHelpers
.
UnwrapSingleStatementBlock
(
falseStatement
);
if
(!
TryGetAssignment
(
trueStatement
,
out
trueAssignment
)
||
!
TryGetAssignment
(
falseStatement
,
out
falseAssignment
))
if
(!
TryGetAssignment
OrThrow
(
trueStatement
,
out
trueAssignment
,
out
trueThrow
)
||
!
TryGetAssignment
OrThrow
(
falseStatement
,
out
falseAssignment
,
out
falseThrow
))
{
return
false
;
}
// Can't convert to `x ? throw ... : throw ...` as there's no best common type between the two (even when
// throwing the same exception type).
if
(
trueThrow
!=
null
&&
falseThrow
!=
null
)
return
false
;
if
(
trueThrow
!=
null
||
falseThrow
!=
null
)
{
if
(!
syntaxFacts
.
SupportsThrowExpression
(
ifOperation
.
Syntax
.
SyntaxTree
.
Options
))
return
false
;
}
// `ref` can't be used with `throw`.
var
isRef
=
trueAssignment
?.
IsRef
==
true
||
falseAssignment
?.
IsRef
==
true
;
if
(
isRef
&&
(
trueThrow
!=
null
||
falseThrow
!=
null
))
return
false
;
// The left side of both assignment statements has to be syntactically identical (modulo
// trivia differences).
if
(!
syntaxFacts
.
AreEquivalent
(
trueAssignment
.
Target
.
Syntax
,
falseAssignment
.
Target
.
Syntax
))
if
(
trueAssignment
!=
null
&&
falseAssignment
!=
null
&&
!
syntaxFacts
.
AreEquivalent
(
trueAssignment
.
Target
.
Syntax
,
falseAssignment
.
Target
.
Syntax
))
{
return
false
;
}
return
UseConditionalExpressionHelpers
.
CanConvert
(
syntaxFacts
,
ifOperation
,
trueAssignment
,
falseAssignment
);
syntaxFacts
,
ifOperation
,
(
IOperation
?)
trueAssignment
??
trueThrow
,
(
IOperation
?)
falseAssignment
??
falseThrow
);
}
private
static
bool
TryGetAssignment
(
IOperation
statement
,
out
ISimpleAssignmentOperation
assignment
)
private
static
bool
TryGetAssignmentOrThrow
(
IOperation
statement
,
out
ISimpleAssignmentOperation
?
assignment
,
out
IThrowOperation
?
throwOperation
)
{
assignment
=
null
;
throwOperation
=
null
;
if
(
statement
is
IThrowOperation
throwOp
)
{
throwOperation
=
throwOp
;
return
true
;
}
// Both the WhenTrue and WhenFalse statements must be of the form:
// target = value;
if
(
!(
statement
is
IExpressionStatementOperation
exprStatement
)
||
!(
exprStatement
.
Operation
is
ISimpleAssignmentOperation
assignmentOp
)
||
assignmentOp
.
Target
=
=
null
)
if
(
statement
is
IExpressionStatementOperation
exprStatement
&&
exprStatement
.
Operation
is
ISimpleAssignmentOperation
assignmentOp
&&
assignmentOp
.
Target
!
=
null
)
{
assignment
=
null
;
return
fals
e
;
assignment
=
assignmentOp
;
return
tru
e
;
}
assignment
=
assignmentOp
;
return
true
;
return
false
;
}
}
}
src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForAssignment/AbstractUseConditionalExpressionForAssignmentCodeFixProvider.cs
浏览文件 @
ce20f709
...
...
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System
;
using
System.Collections.Immutable
;
using
System.Linq
;
...
...
@@ -17,6 +19,7 @@
using
Roslyn.Utilities
;
using
static
Microsoft
.
CodeAnalysis
.
UseConditionalExpression
.
UseConditionalExpressionHelpers
;
using
static
Microsoft
.
CodeAnalysis
.
UseConditionalExpression
.
UseConditionalExpressionCodeFixHelpers
;
using
System.Diagnostics.CodeAnalysis
;
namespace
Microsoft.CodeAnalysis.UseConditionalExpression
{
...
...
@@ -58,48 +61,57 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
Document
document
,
Diagnostic
diagnostic
,
SyntaxEditor
editor
,
CancellationToken
cancellationToken
)
{
var
syntaxFacts
=
document
.
GetLanguageService
<
ISyntaxFactsService
>();
var
syntaxFacts
=
document
.
Get
Required
LanguageService
<
ISyntaxFactsService
>();
var
ifStatement
=
diagnostic
.
AdditionalLocations
[
0
].
FindNode
(
cancellationToken
);
var
semanticModel
=
await
document
.
GetSemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
ifOperation
=
(
IConditionalOperation
)
semanticModel
.
GetOperation
(
ifStatement
);
var
semanticModel
=
await
document
.
Get
Required
SemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
ifOperation
=
(
IConditionalOperation
)
semanticModel
.
GetOperation
(
ifStatement
)
!
;
if
(!
UseConditionalExpressionForAssignmentHelpers
.
TryMatchPattern
(
syntaxFacts
,
ifOperation
,
out
var
trueAssignment
,
out
var
falseAssignment
))
out
var
trueAssignment
,
out
var
trueThrow
,
out
var
falseAssignment
,
out
var
falseThrow
))
{
return
;
}
var
trueSatement
=
((
IOperation
?)
trueAssignment
??
trueThrow
)!;
var
falseStatement
=
((
IOperation
?)
falseAssignment
??
falseThrow
)!;
var
conditionalExpression
=
await
CreateConditionalExpressionAsync
(
document
,
ifOperation
,
trueAssignment
.
Parent
,
falseAssignment
.
Parent
,
trueAssignment
.
Value
,
falseAssignment
.
Value
,
trueAssignment
.
IsRef
,
cancellationToken
).
ConfigureAwait
(
false
);
document
,
ifOperation
,
trueSatement
,
falseStatement
,
trueAssignment
?.
Value
??
trueThrow
?.
Exception
,
falseAssignment
?.
Value
??
falseThrow
?.
Exception
,
trueAssignment
?.
IsRef
==
true
,
cancellationToken
).
ConfigureAwait
(
false
);
// See if we're assigning to a variable declared directly above the if statement. If so,
// try to inline the conditional directly into the initializer for that variable.
if
(
!
TryConvertWhenAssignmentToLocalDeclaredImmediateAbove
(
if
(
TryConvertWhenAssignmentToLocalDeclaredImmediateAbove
(
syntaxFacts
,
editor
,
ifOperation
,
trueAssignment
,
falseAssignment
,
conditionalExpression
))
{
// If not, just replace the if-statement with a single assignment of the new
// conditional.
ConvertOnlyIfToConditionalExpression
(
editor
,
ifOperation
,
trueAssignment
,
conditionalExpression
);
return
;
}
// If not, just replace the if-statement with a single assignment of the new
// conditional.
ConvertOnlyIfToConditionalExpression
(
editor
,
ifOperation
,
(
trueAssignment
??
falseAssignment
)!,
conditionalExpression
);
}
private
void
ConvertOnlyIfToConditionalExpression
(
SyntaxEditor
editor
,
IConditionalOperation
ifOperation
,
ISimpleAssignmentOperation
trueA
ssignment
,
ISimpleAssignmentOperation
a
ssignment
,
TExpressionSyntax
conditionalExpression
)
{
var
generator
=
editor
.
Generator
;
var
ifStatement
=
(
TIfStatementSyntax
)
ifOperation
.
Syntax
;
var
expressionStatement
=
(
TStatementSyntax
)
generator
.
ExpressionStatement
(
generator
.
AssignmentStatement
(
trueA
ssignment
.
Target
.
Syntax
,
a
ssignment
.
Target
.
Syntax
,
conditionalExpression
)).
WithTriviaFrom
(
ifStatement
);
editor
.
ReplaceNode
(
...
...
@@ -109,7 +121,8 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
private
bool
TryConvertWhenAssignmentToLocalDeclaredImmediateAbove
(
ISyntaxFactsService
syntaxFacts
,
SyntaxEditor
editor
,
IConditionalOperation
ifOperation
,
ISimpleAssignmentOperation
trueAssignment
,
ISimpleAssignmentOperation
falseAssignment
,
ISimpleAssignmentOperation
?
trueAssignment
,
ISimpleAssignmentOperation
?
falseAssignment
,
TExpressionSyntax
conditionalExpression
)
{
if
(!
TryFindMatchingLocalDeclarationImmediatelyAbove
(
...
...
@@ -139,20 +152,40 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
}
private
bool
TryFindMatchingLocalDeclarationImmediatelyAbove
(
IConditionalOperation
ifOperation
,
ISimpleAssignmentOperation
trueAssignment
,
ISimpleAssignmentOperation
falseAssignment
,
out
IVariableDeclarationGroupOperation
localDeclaration
,
out
IVariableDeclaratorOperation
declarator
)
IConditionalOperation
ifOperation
,
ISimpleAssignmentOperation
?
trueAssignment
,
ISimpleAssignmentOperation
?
falseAssignment
,
[
NotNullWhen
(
true
)]
out
IVariableDeclarationGroupOperation
?
localDeclaration
,
[
NotNullWhen
(
true
)]
out
IVariableDeclaratorOperation
?
declarator
)
{
localDeclaration
=
null
;
declarator
=
null
;
// See if both assignments are to the same local.
if
(!(
trueAssignment
.
Target
is
ILocalReferenceOperation
trueLocal
)
||
!(
falseAssignment
.
Target
is
ILocalReferenceOperation
falseLocal
)
||
!
Equals
(
trueLocal
.
Local
,
falseLocal
.
Local
))
ILocalSymbol
?
local
=
null
;
if
(
trueAssignment
!=
null
)
{
return
false
;
if
(!(
trueAssignment
.
Target
is
ILocalReferenceOperation
trueLocal
))
return
false
;
local
=
trueLocal
.
Local
;
}
if
(
falseAssignment
!=
null
)
{
if
(!(
falseAssignment
.
Target
is
ILocalReferenceOperation
falseLocal
))
return
false
;
// See if both assignments are to the same local.
if
(
local
!=
null
&&
!
Equals
(
local
,
falseLocal
.
Local
))
return
false
;
local
=
falseLocal
.
Local
;
}
// We weren't assigning to a local.
if
(
local
==
null
)
return
false
;
// If so, see if that local was declared immediately above the if-statement.
if
(!(
ifOperation
.
Parent
is
IBlockOperation
parentBlock
))
{
...
...
@@ -190,7 +223,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
declarator
=
declarators
[
0
];
var
variable
=
declarator
.
Symbol
;
if
(!
Equals
(
variable
,
trueLocal
.
L
ocal
))
if
(!
Equals
(
variable
,
l
ocal
))
{
// wasn't a declaration of the local we're assigning to.
return
false
;
...
...
src/Analyzers/Core/CodeFixes/UseConditionalExpression/ForReturn/AbstractUseConditionalExpressionForReturnCodeFixProvider.cs
浏览文件 @
ce20f709
...
...
@@ -52,8 +52,8 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
var
syntaxFacts
=
document
.
GetRequiredLanguageService
<
ISyntaxFactsService
>();
var
ifStatement
=
(
TIfStatementSyntax
)
diagnostic
.
AdditionalLocations
[
0
].
FindNode
(
cancellationToken
);
var
semanticModel
=
await
document
.
GetSemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
ifOperation
=
(
IConditionalOperation
)
semanticModel
.
GetOperation
(
ifStatement
);
var
semanticModel
=
await
document
.
Get
Required
SemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
ifOperation
=
(
IConditionalOperation
)
semanticModel
.
GetOperation
(
ifStatement
)
!
;
if
(!
UseConditionalExpressionForReturnHelpers
.
TryMatchPattern
(
syntaxFacts
,
ifOperation
,
...
...
@@ -66,13 +66,17 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
var
trueSatement
=
((
IOperation
?)
trueReturn
??
trueThrow
)!;
var
falseStatement
=
((
IOperation
?)
falseReturn
??
falseThrow
)!;
// `ref` can't be used with `throw`.
var
isRef
=
IsRef
(
trueReturn
??
falseReturn
);
if
(
isRef
&&
(
trueThrow
!=
null
||
falseThrow
!=
null
))
return
;
var
conditionalExpression
=
await
CreateConditionalExpressionAsync
(
document
,
ifOperation
,
trueSatement
,
falseStatement
,
trueSatement
,
falseStatement
,
trueReturn
?.
ReturnedValue
??
trueThrow
?.
Exception
,
falseReturn
?.
ReturnedValue
??
falseThrow
?.
Exception
,
IsRef
(
trueReturn
)
,
cancellationToken
).
ConfigureAwait
(
false
);
isRef
,
cancellationToken
).
ConfigureAwait
(
false
);
var
generatorInternal
=
document
.
GetRequiredLanguageService
<
SyntaxGeneratorInternal
>();
var
returnStatement
=
trueReturn
?.
Kind
==
OperationKind
.
YieldReturn
...
...
src/Analyzers/VisualBasic/Tests/UseConditionalExpression/UseConditionalExpressionForAssignmentTests.vb
浏览文件 @
ce20f709
...
...
@@ -37,6 +37,37 @@ class C
end class"
)
End
Function
<
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)
>
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)
>
Public
Async
Function
TestNotWithThrow1
()
As
Task
Await
TestMissingAsync
(
"
class C
sub M(i as integer)
[||]if true
throw new System.Exception()
else
i = 1
end if
end sub
end class"
)
End
Function
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)
>
Public
Async
Function
TestNotWithThrow2
()
As
Task
Await
TestMissingAsync
(
"
class C
sub M(i as integer)
[||]if true
i = 0
else
throw new System.Exception()
end if
end sub
end class"
)
End
Function
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)
>
Public
Async
Function
TestOnSimpleAssignmentNoBlocks
()
As
Task
Await
TestInRegularAndScriptAsync
(
...
...
src/Analyzers/VisualBasic/Tests/UseConditionalExpression/UseConditionalExpressionForReturnTests.vb
浏览文件 @
ce20f709
...
...
@@ -37,6 +37,37 @@ class C
end class"
)
End
Function
<
WorkItem
(
43291
,
"https://github.com/dotnet/roslyn/issues/43291"
)
>
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)
>
Public
Async
Function
TestNotWithThrow1
()
As
Task
Await
TestMissingAsync
(
"
class C
function M() as integer
[||]if true
return 0
else
throw new System.Exception()
end if
end function
end class"
)
End
Function
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)
>
Public
Async
Function
TestNotWithThrow2
()
As
Task
Await
TestMissingAsync
(
"
class C
function M() as integer
[||]if true
throw new System.Exception()
else
return 1
end if
end function
end class"
)
End
Function
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseConditionalExpression
)
>
Public
Async
Function
TestOnSimpleReturnNoBlocks
()
As
Task
Await
TestInRegularAndScriptAsync
(
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录