Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
6dc35229
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,发现更多精彩内容 >>
未验证
提交
6dc35229
编写于
1月 10, 2018
作者:
J
Julien Couvreur
提交者:
GitHub
1月 10, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
UseExplicitType for var in deconstruction (#23975)
上级
06efa591
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
250 addition
and
10 deletion
+250
-10
src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
+3
-3
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs
...ilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs
+1
-0
src/EditorFeatures/CSharpTest/Diagnostics/UseImplicitOrExplicitType/UseExplicitTypeTests.cs
...nostics/UseImplicitOrExplicitType/UseExplicitTypeTests.cs
+168
-1
src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpUseExplicitTypeDiagnosticAnalyzer.cs
...tics/Analyzers/CSharpUseExplicitTypeDiagnosticAnalyzer.cs
+12
-0
src/Features/CSharp/Portable/TypeStyle/UseExplicitTypeCodeFixProvider.cs
...harp/Portable/TypeStyle/UseExplicitTypeCodeFixProvider.cs
+66
-6
未找到文件。
src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
浏览文件 @
6dc35229
...
...
@@ -249,7 +249,7 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics,
var
variables
=
node
.
Variable
;
if
(
variables
.
IsDeconstructionLeft
())
{
var
valuePlaceholder
=
new
BoundDeconstructValuePlaceholder
(
_syntax
.
Expression
,
collectionEscape
,
iterationVariableType
)
{
WasCompilerGenerated
=
true
}
;
var
valuePlaceholder
=
new
BoundDeconstructValuePlaceholder
(
_syntax
.
Expression
,
collectionEscape
,
iterationVariableType
)
.
MakeCompilerGenerated
()
;
DeclarationExpressionSyntax
declaration
=
null
;
ExpressionSyntax
expression
=
null
;
BoundDeconstructionAssignmentOperator
deconstruction
=
BindDeconstruction
(
...
...
@@ -268,7 +268,7 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics,
hasErrors
=
true
;
}
deconstructStep
=
new
BoundForEachDeconstructStep
(
variables
,
deconstruction
,
valuePlaceholder
);
deconstructStep
=
new
BoundForEachDeconstructStep
(
variables
,
deconstruction
,
valuePlaceholder
)
.
MakeCompilerGenerated
()
;
}
else
if
(!
node
.
HasErrors
)
{
...
...
@@ -277,7 +277,7 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics,
hasErrors
=
true
;
}
boundIterationVariableType
=
new
BoundTypeExpression
(
variables
,
aliasOpt
:
null
,
type
:
iterationVariableType
);
boundIterationVariableType
=
new
BoundTypeExpression
(
variables
,
aliasOpt
:
null
,
type
:
iterationVariableType
)
.
MakeCompilerGenerated
()
;
break
;
}
default
:
...
...
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDeconstructTests.cs
浏览文件 @
6dc35229
...
...
@@ -1227,6 +1227,7 @@ public void Deconstruct(out int a, out int b)
Assert
.
Equal
(
"(System.Int32 a, System.Int32 b)"
,
tuple2
.
ToTestDisplayString
());
var
underlying2
=
tuple2
.
TupleUnderlyingType
;
Assert
.
Equal
(
"System.ValueTuple<System.Int32, System.Int32>[missing]"
,
underlying2
.
ToTestDisplayString
());
Assert
.
Equal
(
"(System.Int32 a, System.Int32 b)"
,
model
.
GetTypeInfo
(
ab
).
ConvertedType
.
ToTestDisplayString
());
}
[
Fact
]
...
...
src/EditorFeatures/CSharpTest/Diagnostics/UseImplicitOrExplicitType/UseExplicitTypeTests.cs
浏览文件 @
6dc35229
...
...
@@ -6,7 +6,6 @@
using
Microsoft.CodeAnalysis.CodeStyle
;
using
Microsoft.CodeAnalysis.CSharp.CodeStyle
;
using
Microsoft.CodeAnalysis.CSharp.Diagnostics.TypeStyle
;
using
Microsoft.CodeAnalysis.CSharp.Test.Utilities
;
using
Microsoft.CodeAnalysis.CSharp.TypeStyle
;
using
Microsoft.CodeAnalysis.Diagnostics
;
using
Microsoft.CodeAnalysis.Options
;
...
...
@@ -462,6 +461,174 @@ void Method()
}"
,
new
TestParameters
(
options
:
ExplicitTypeEverywhere
()));
}
[
WpfFact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseExplicitType
)]
[
WorkItem
(
23752
,
"https://github.com/dotnet/roslyn/issues/23752"
)]
public
async
Task
OnDeconstructionVar
()
{
await
TestInRegularAndScriptAsync
(
@"using System;
class Program
{
void M()
{
[|var|] (x, y) = new Program();
}
void Deconstruct(out int i, out string s) { i = 1; s = ""hello""; }
}"
,
@"using System;
class Program
{
void M()
{
(int x, string y) = new Program();
}
void Deconstruct(out int i, out string s) { i = 1; s = ""hello""; }
}"
,
options
:
ExplicitTypeEverywhere
());
}
[
WpfFact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseExplicitType
)]
[
WorkItem
(
23752
,
"https://github.com/dotnet/roslyn/issues/23752"
)]
public
async
Task
OnNestedDeconstructionVar
()
{
await
TestInRegularAndScriptAsync
(
@"using System;
class Program
{
void M()
{
[|var|] (x, (y, z)) = new Program();
}
void Deconstruct(out int i, out Program s) { i = 1; s = null; }
}"
,
@"using System;
class Program
{
void M()
{
(int x, (int y, Program z)) = new Program();
}
void Deconstruct(out int i, out Program s) { i = 1; s = null; }
}"
,
options
:
ExplicitTypeEverywhere
());
}
[
WpfFact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseExplicitType
)]
[
WorkItem
(
23752
,
"https://github.com/dotnet/roslyn/issues/23752"
)]
public
async
Task
OnBadlyFormattedNestedDeconstructionVar
()
{
await
TestInRegularAndScriptAsync
(
@"using System;
class Program
{
void M()
{
[|var|](x,(y,z)) = new Program();
}
void Deconstruct(out int i, out Program s) { i = 1; s = null; }
}"
,
@"using System;
class Program
{
void M()
{
(int x, (int y, Program z)) = new Program();
}
void Deconstruct(out int i, out Program s) { i = 1; s = null; }
}"
,
options
:
ExplicitTypeEverywhere
());
}
[
WpfFact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseExplicitType
)]
[
WorkItem
(
23752
,
"https://github.com/dotnet/roslyn/issues/23752"
)]
public
async
Task
OnForeachNestedDeconstructionVar
()
{
await
TestInRegularAndScriptAsync
(
@"using System;
class Program
{
void M()
{
foreach ([|var|] (x, (y, z)) in new[] { new Program() } { }
}
void Deconstruct(out int i, out Program s) { i = 1; s = null; }
}"
,
@"using System;
class Program
{
void M()
{
foreach ((int x, (int y, Program z)) in new[] { new Program() } { }
}
void Deconstruct(out int i, out Program s) { i = 1; s = null; }
}"
,
options
:
ExplicitTypeEverywhere
());
}
[
WpfFact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseExplicitType
)]
[
WorkItem
(
23752
,
"https://github.com/dotnet/roslyn/issues/23752"
)]
public
async
Task
OnNestedDeconstructionVarWithTrivia
()
{
await
TestInRegularAndScriptAsync
(
@"using System;
class Program
{
void M()
{
/*before*/[|var|]/*after*/ (/*x1*/x/*x2*/, /*yz1*/(/*y1*/y/*y2*/, /*z1*/z/*z2*/)/*yz2*/) /*end*/ = new Program();
}
void Deconstruct(out int i, out Program s) { i = 1; s = null; }
}"
,
@"using System;
class Program
{
void M()
{
/*before*//*after*/(/*x1*/int x/*x2*/, /*yz1*/(/*y1*/int y/*y2*/, /*z1*/Program z/*z2*/)/*yz2*/) /*end*/ = new Program();
}
void Deconstruct(out int i, out Program s) { i = 1; s = null; }
}"
,
options
:
ExplicitTypeEverywhere
());
}
[
WpfFact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseExplicitType
)]
[
WorkItem
(
23752
,
"https://github.com/dotnet/roslyn/issues/23752"
)]
public
async
Task
OnDeconstructionVarWithDiscard
()
{
await
TestInRegularAndScriptAsync
(
@"using System;
class Program
{
void M()
{
[|var|] (x, _) = new Program();
}
void Deconstruct(out int i, out string s) { i = 1; s = ""hello""; }
}"
,
@"using System;
class Program
{
void M()
{
(int x, string _) = new Program();
}
void Deconstruct(out int i, out string s) { i = 1; s = ""hello""; }
}"
,
options
:
ExplicitTypeEverywhere
());
}
[
WpfFact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseExplicitType
)]
[
WorkItem
(
23752
,
"https://github.com/dotnet/roslyn/issues/23752"
)]
public
async
Task
OnDeconstructionVarWithErrorType
()
{
await
TestInRegularAndScriptAsync
(
@"using System;
class Program
{
void M()
{
[|var|] (x, y) = new Program();
}
void Deconstruct(out int i, out Error s) { i = 1; s = null; }
}"
,
@"using System;
class Program
{
void M()
{
(int x, Error y) = new Program();
}
void Deconstruct(out int i, out Error s) { i = 1; s = null; }
}"
,
options
:
ExplicitTypeEverywhere
());
}
[
WpfFact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseExplicitType
)]
public
async
Task
OnForEachVarWithExplicitType
()
{
...
...
src/Features/CSharp/Portable/Diagnostics/Analyzers/CSharpUseExplicitTypeDiagnosticAnalyzer.cs
浏览文件 @
6dc35229
...
...
@@ -81,6 +81,18 @@ protected override bool TryAnalyzeVariableDeclaration(TypeSyntax typeName, Seman
{
issueSpan
=
default
;
// var (x, y) = e;
// foreach (var (x, y) in e) ...
if
(
typeName
.
IsParentKind
(
SyntaxKind
.
DeclarationExpression
))
{
var
parent
=
(
DeclarationExpressionSyntax
)
typeName
.
Parent
;
if
(
parent
.
Designation
.
IsKind
(
SyntaxKind
.
ParenthesizedVariableDesignation
))
{
issueSpan
=
typeName
.
Span
;
return
true
;
}
}
// If it is currently not var, explicit typing exists, return.
// this also takes care of cases where var is mapped to a named type via an alias or a class declaration.
if
(!
typeName
.
IsTypeInferred
(
semanticModel
))
...
...
src/Features/CSharp/Portable/TypeStyle/UseExplicitTypeCodeFixProvider.cs
浏览文件 @
6dc35229
...
...
@@ -13,6 +13,7 @@
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.Diagnostics
;
using
Microsoft.CodeAnalysis.Editing
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.CSharp.TypeStyle
...
...
@@ -53,6 +54,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
var
declarationContext
=
node
.
Parent
;
TypeSyntax
typeSyntax
=
null
;
ParenthesizedVariableDesignationSyntax
parensDesignation
=
null
;
if
(
declarationContext
is
VariableDeclarationSyntax
varDecl
)
{
typeSyntax
=
varDecl
.
Type
;
...
...
@@ -64,21 +66,79 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
else
if
(
declarationContext
is
DeclarationExpressionSyntax
declarationExpression
)
{
typeSyntax
=
declarationExpression
.
Type
;
if
(
declarationExpression
.
Designation
.
IsKind
(
SyntaxKind
.
ParenthesizedVariableDesignation
))
{
parensDesignation
=
(
ParenthesizedVariableDesignationSyntax
)
declarationExpression
.
Designation
;
}
}
else
{
Contract
.
Fail
(
$"unhandled kind
{
declarationContext
.
Kind
().
ToString
()}
"
);
}
var
typeSymbol
=
semanticModel
.
GetTypeInfo
(
typeSyntax
).
ConvertedType
;
if
(
parensDesignation
is
null
)
{
var
typeSymbol
=
semanticModel
.
GetTypeInfo
(
typeSyntax
).
ConvertedType
;
var
typeName
=
typeSymbol
.
GenerateTypeSyntax
()
.
WithLeadingTrivia
(
node
.
GetLeadingTrivia
())
.
WithTrailingTrivia
(
node
.
GetTrailingTrivia
());
Debug
.
Assert
(!
typeName
.
ContainsDiagnostics
,
"Explicit type replacement likely introduced an error in code"
);
editor
.
ReplaceNode
(
node
,
typeName
);
}
else
{
var
tupleTypeSymbol
=
semanticModel
.
GetTypeInfo
(
typeSyntax
.
Parent
).
ConvertedType
;
var
leadingTrivia
=
node
.
GetLeadingTrivia
()
.
Concat
(
parensDesignation
.
GetAllPrecedingTriviaToPreviousToken
().
Where
(
t
=>
!
t
.
IsWhitespace
()).
Select
(
t
=>
t
.
WithoutAnnotations
(
SyntaxAnnotation
.
ElasticAnnotation
)));
var
tupleDeclaration
=
GenerateTupleDeclaration
(
tupleTypeSymbol
,
parensDesignation
).
WithLeadingTrivia
(
leadingTrivia
);
editor
.
ReplaceNode
(
declarationContext
,
tupleDeclaration
);
}
}
private
ExpressionSyntax
GenerateTupleDeclaration
(
ITypeSymbol
typeSymbol
,
ParenthesizedVariableDesignationSyntax
parensDesignation
)
{
Debug
.
Assert
(
typeSymbol
.
IsTupleType
);
var
elements
=
((
INamedTypeSymbol
)
typeSymbol
).
TupleElements
;
Debug
.
Assert
(
elements
.
Length
==
parensDesignation
.
Variables
.
Count
);
var
typeName
=
typeSymbol
.
GenerateTypeSyntax
()
.
WithLeadingTrivia
(
node
.
GetLeadingTrivia
())
.
WithTrailingTrivia
(
node
.
GetTrailingTrivia
());
var
builder
=
ArrayBuilder
<
SyntaxNode
>.
GetInstance
(
elements
.
Length
);
for
(
int
i
=
0
;
i
<
elements
.
Length
;
i
++)
{
var
designation
=
parensDesignation
.
Variables
[
i
];
var
type
=
elements
[
i
].
Type
;
ExpressionSyntax
newDeclaration
;
switch
(
designation
.
Kind
())
{
case
SyntaxKind
.
SingleVariableDesignation
:
case
SyntaxKind
.
DiscardDesignation
:
var
typeName
=
type
.
GenerateTypeSyntax
();
newDeclaration
=
SyntaxFactory
.
DeclarationExpression
(
typeName
,
designation
);
break
;
case
SyntaxKind
.
ParenthesizedVariableDesignation
:
newDeclaration
=
GenerateTupleDeclaration
(
type
,
(
ParenthesizedVariableDesignationSyntax
)
designation
);
break
;
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
designation
.
Kind
());
}
newDeclaration
=
newDeclaration
.
WithLeadingTrivia
(
designation
.
GetAllPrecedingTriviaToPreviousToken
())
.
WithTrailingTrivia
(
designation
.
GetTrailingTrivia
());
builder
.
Add
(
SyntaxFactory
.
Argument
(
newDeclaration
));
}
Debug
.
Assert
(!
typeName
.
ContainsDiagnostics
,
"Explicit type replacement likely introduced an error in code"
);
var
separatorBuilder
=
ArrayBuilder
<
SyntaxToken
>.
GetInstance
(
builder
.
Count
-
1
,
SyntaxFactory
.
Token
(
leading
:
default
,
SyntaxKind
.
CommaToken
,
trailing
:
default
)
);
editor
.
ReplaceNode
(
node
,
typeName
);
return
SyntaxFactory
.
TupleExpression
(
SyntaxFactory
.
Token
(
SyntaxKind
.
OpenParenToken
).
WithTrailingTrivia
(),
SyntaxFactory
.
SeparatedList
(
builder
.
ToImmutableAndFree
(),
separatorBuilder
.
ToImmutableAndFree
()),
SyntaxFactory
.
Token
(
SyntaxKind
.
CloseParenToken
))
.
WithTrailingTrivia
(
parensDesignation
.
GetTrailingTrivia
());
}
private
class
MyCodeAction
:
CodeAction
.
DocumentChangeAction
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录