Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
a1c7e5d3
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,发现更多精彩内容 >>
提交
a1c7e5d3
编写于
9月 01, 2017
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add tests.
上级
b1890ac2
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
469 addition
and
4 deletion
+469
-4
src/EditorFeatures/CSharpTest/UseDeconstruction/UseDeconstructionTests.cs
...es/CSharpTest/UseDeconstruction/UseDeconstructionTests.cs
+445
-0
src/EditorFeatures/TestUtilities/Traits.cs
src/EditorFeatures/TestUtilities/Traits.cs
+1
-0
src/Features/CSharp/Portable/UseDeconstruction/CSharpUseDeconstructionCodeFixProvider.cs
...eDeconstruction/CSharpUseDeconstructionCodeFixProvider.cs
+13
-3
src/Features/CSharp/Portable/UseDeconstruction/CSharpUseDeconstructionDiagnosticAnalyzer.cs
...construction/CSharpUseDeconstructionDiagnosticAnalyzer.cs
+10
-1
未找到文件。
src/EditorFeatures/CSharpTest/UseDeconstruction/UseDeconstructionTests.cs
0 → 100644
浏览文件 @
a1c7e5d3
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.CodeFixes
;
using
Microsoft.CodeAnalysis.CSharp.UseDeconstruction
;
using
Microsoft.CodeAnalysis.Diagnostics
;
using
Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics
;
using
Roslyn.Test.Utilities
;
using
Xunit
;
namespace
Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseDeconstruction
{
public
class
UseDeconstructionTests
:
AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal
override
(
DiagnosticAnalyzer
,
CodeFixProvider
)
CreateDiagnosticProviderAndFixer
(
Workspace
workspace
)
=>
(
new
CSharpUseDeconstructionDiagnosticAnalyzer
(),
new
CSharpUseDeconstructionCodeFixProvider
());
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestVar
()
{
await
TestInRegularAndScriptAsync
(
@"class C
{
void M()
{
var [|t1|] = GetPerson();
}
(string name, int age) GetPerson() => default;
}"
,
@"class C
{
void M()
{
var (name, age) = GetPerson();
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestNotIfNameInInnerScope
()
{
await
TestMissingInRegularAndScriptAsync
(
@"class C
{
void M()
{
var [|t1|] = GetPerson();
{
int age;
}
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestNotIfNameInOuterScope
()
{
await
TestMissingInRegularAndScriptAsync
(
@"class C
{
int age;
void M()
{
var [|t1|] = GetPerson();
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestUpdateReference
()
{
await
TestInRegularAndScriptAsync
(
@"class C
{
void M()
{
var [|t1|] = GetPerson();
Console.WriteLine(t1.name + "" "" + t1.age);
}
(string name, int age) GetPerson() => default;
}"
,
@"class C
{
void M()
{
var (name, age) = GetPerson();
Console.WriteLine(name + "" "" + age);
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestTupleType
()
{
await
TestInRegularAndScriptAsync
(
@"class C
{
void M()
{
(int name, int age) [|t1|] = GetPerson();
Console.WriteLine(t1.name + "" "" + t1.age);
}
(string name, int age) GetPerson() => default;
}"
,
@"class C
{
void M()
{
(int name, int age) = GetPerson();
Console.WriteLine(name + "" "" + age);
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestVarInForEach
()
{
await
TestInRegularAndScriptAsync
(
@"using System.Collections.Generic;
class C
{
void M()
{
foreach (var [|t1|] in GetPeople())
Console.WriteLine(t1.name + "" "" + t1.age);
}
IEnumerable<(string name, int age)> GetPeople() => default;
}"
,
@"using System.Collections.Generic;
class C
{
void M()
{
foreach (var (name, age) in GetPeople())
Console.WriteLine(name + "" "" + age);
}
IEnumerable<(string name, int age)> GetPeople() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestTupleTypeInForEach
()
{
await
TestInRegularAndScriptAsync
(
@"using System.Collections.Generic;
class C
{
void M()
{
foreach ((string name, int age) [|t1|] in GetPeople())
Console.WriteLine(t1.name + "" "" + t1.age);
}
IEnumerable<(string name, int age)> GetPeople() => default;
}"
,
@"using System.Collections.Generic;
class C
{
void M()
{
foreach ((string name, int age) in GetPeople())
Console.WriteLine(name + "" "" + age);
}
IEnumerable<(string name, int age)> GetPeople() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestFixAll1
()
{
await
TestInRegularAndScriptAsync
(
@"class C
{
void M()
{
var {|FixAllInDocument:t1|} = GetPerson();
var t2 = GetPerson();
}
(string name, int age) GetPerson() => default;
}"
,
@"class C
{
void M()
{
var (name, age) = GetPerson();
var t2 = GetPerson();
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestFixAll2
()
{
await
TestInRegularAndScriptAsync
(
@"class C
{
void M()
{
var {|FixAllInDocument:t1|} = GetPerson();
}
void M2()
{
var t2 = GetPerson();
}
(string name, int age) GetPerson() => default;
}"
,
@"class C
{
void M()
{
var (name, age) = GetPerson();
}
void M2()
{
var (name, age) = GetPerson();
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestFixAll3
()
{
await
TestInRegularAndScriptAsync
(
@"class C
{
void M()
{
(string name1, int age1) {|FixAllInDocument:t1|} = GetPerson();
(string name2, int age2) t2 = GetPerson();
}
(string name, int age) GetPerson() => default;
}"
,
@"class C
{
void M()
{
(string name1, int age1) = GetPerson();
(string name2, int age2) = GetPerson();
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestFixAll4
()
{
await
TestInRegularAndScriptAsync
(
@"class C
{
void M()
{
(string name, int age) {|FixAllInDocument:t1|} = GetPerson();
(string name, int age) t2 = GetPerson();
}
(string name, int age) GetPerson() => default;
}"
,
@"class C
{
void M()
{
(string name, int age) = GetPerson();
(string name, int age) t2 = GetPerson();
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestNotIfDefaultTupleNameWithVar
()
{
await
TestMissingInRegularAndScriptAsync
(
@"class C
{
void M()
{
var [|t1|] = GetPerson();
}
(string, int) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestWithUserNamesThatMatchDefaultTupleNameWithVar1
()
{
await
TestInRegularAndScriptAsync
(
@"class C
{
void M()
{
var [|t1|] = GetPerson();
}
(string Item1, int Item2) GetPerson() => default;
}"
,
@"class C
{
void M()
{
var (Item1, Item2) = GetPerson();
}
(string Item1, int Item2) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestWithUserNamesThatMatchDefaultTupleNameWithVar2
()
{
await
TestInRegularAndScriptAsync
(
@"class C
{
void M()
{
var [|t1|] = GetPerson();
Console.WriteLine(t1.Item1);
}
(string Item1, int Item2) GetPerson() => default;
}"
,
@"class C
{
void M()
{
var (Item1, Item2) = GetPerson();
Console.WriteLine(Item1);
}
(string Item1, int Item2) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestNotIfDefaultTupleNameWithTupleType
()
{
await
TestMissingInRegularAndScriptAsync
(
@"class C
{
void M()
{
(string, int) [|t1|] = GetPerson();
}
(string, int) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestNotIfTupleIsUsed
()
{
await
TestMissingInRegularAndScriptAsync
(
@"class C
{
void M()
{
var [|t1|] = GetPerson();
Console.WriteLine(t1);
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestNotIfTupleMethodIsUsed
()
{
await
TestMissingInRegularAndScriptAsync
(
@"class C
{
void M()
{
var [|t1|] = GetPerson();
Console.WriteLine(t1.ToString());
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestNotIfTupleDefaultElementNameUsed
()
{
await
TestMissingInRegularAndScriptAsync
(
@"class C
{
void M()
{
var [|t1|] = GetPerson();
Console.WriteLine(t1.Item1);
}
(string name, int age) GetPerson() => default;
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseDeconstruction
)]
public
async
Task
TestNotIfTupleRandomNameUsed
()
{
await
TestMissingInRegularAndScriptAsync
(
@"class C
{
void M()
{
var [|t1|] = GetPerson();
Console.WriteLine(t1.Unknown);
}
(string name, int age) GetPerson() => default;
}"
);
}
}
}
src/EditorFeatures/TestUtilities/Traits.cs
浏览文件 @
a1c7e5d3
...
...
@@ -102,6 +102,7 @@ public static class Features
public
const
string
CodeActionsUseAutoProperty
=
"CodeActions.UseAutoProperty"
;
public
const
string
CodeActionsUseCoalesceExpression
=
"CodeActions.UseCoalesceExpression"
;
public
const
string
CodeActionsUseCollectionInitializer
=
"CodeActions.UseCollectionInitializer"
;
public
const
string
CodeActionsUseDeconstruction
=
"CodeActions.UseDeconstruction"
;
public
const
string
CodeActionsUseDefaultLiteral
=
"CodeActions.UseDefaultLiteral"
;
public
const
string
CodeActionsUseInferredMemberName
=
"CodeActions.UseInferredMemberName"
;
public
const
string
CodeActionsUseExpressionBody
=
"CodeActions.UseExpressionBody"
;
...
...
src/Features/CSharp/Portable/UseDeconstruction/CSharpUseDeconstructionCodeFixProvider.cs
浏览文件 @
a1c7e5d3
...
...
@@ -68,7 +68,11 @@ private SyntaxNode UpdateRoot(SemanticModel semanticModel, SyntaxNode root, Synt
{
editor
.
ReplaceNode
(
variableDeclaration
.
Parent
,
CreateDeconstructionStatement
(
tupleType
,
(
LocalDeclarationStatementSyntax
)
variableDeclaration
.
Parent
,
variableDeclarator
));
(
current
,
_
)
=>
{
var
currentDeclarationStatement
=
(
LocalDeclarationStatementSyntax
)
current
;
return
CreateDeconstructionStatement
(
tupleType
,
currentDeclarationStatement
,
currentDeclarationStatement
.
Declaration
.
Variables
[
0
]);
});
}
}
else
if
(
node
is
ForEachStatementSyntax
forEachStatement
)
...
...
@@ -80,13 +84,19 @@ private SyntaxNode UpdateRoot(SemanticModel semanticModel, SyntaxNode root, Synt
{
editor
.
ReplaceNode
(
forEachStatement
,
CreateForEachVariableStatement
(
tupleType
,
forEachStatem
ent
));
(
current
,
_
)
=>
CreateForEachVariableStatement
(
tupleType
,
(
ForEachStatementSyntax
)
curr
ent
));
}
}
foreach
(
var
memberAccess
in
memberAccessExpressions
.
NullToEmpty
())
{
editor
.
ReplaceNode
(
memberAccess
,
memberAccess
.
Name
.
WithTriviaFrom
(
memberAccess
));
editor
.
ReplaceNode
(
memberAccess
,
(
current
,
_
)
=>
{
var
currentMemberAccess
=
(
MemberAccessExpressionSyntax
)
current
;
return
currentMemberAccess
.
Name
.
WithTriviaFrom
(
currentMemberAccess
);
});
}
return
editor
.
GetChangedRoot
();
...
...
src/Features/CSharp/Portable/UseDeconstruction/CSharpUseDeconstructionDiagnosticAnalyzer.cs
浏览文件 @
a1c7e5d3
...
...
@@ -177,6 +177,15 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context)
return
false
;
}
// All tuple elements must have been explicitly provided by the user.
foreach
(
var
element
in
tupleType
.
TupleElements
)
{
if
(
element
.
IsImplicitlyDeclared
)
{
return
false
;
}
}
var
variableName
=
identifier
.
ValueText
;
var
references
=
ArrayBuilder
<
MemberAccessExpressionSyntax
>.
GetInstance
();
...
...
@@ -278,7 +287,7 @@ private bool IsViableTupleTypeSyntax(TypeSyntax type)
return
false
;
}
if
(
field
.
CorrespondingTupleField
==
fiel
d
)
if
(
field
.
IsImplicitlyDeclare
d
)
{
// They're referring to .Item1-.ItemN. We can't update this to refer to the local
return
false
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录