Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
9131a36c
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,发现更多精彩内容 >>
提交
9131a36c
编写于
5月 04, 2020
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Tweaks
上级
31425420
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
42 addition
and
48 deletion
+42
-48
src/Features/Core/Portable/CodeFixes/AddExplicitCast/AbstractAddExplicitCastCodeFixProvider.cs
...AddExplicitCast/AbstractAddExplicitCastCodeFixProvider.cs
+42
-48
未找到文件。
src/Features/Core/Portable/CodeFixes/AddExplicitCast/AbstractAddExplicitCastCodeFixProvider.cs
浏览文件 @
9131a36c
...
@@ -11,6 +11,7 @@
...
@@ -11,6 +11,7 @@
using
System.Linq
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis
;
using
Microsoft.CodeAnalysis.CodeActions
;
using
Microsoft.CodeAnalysis.CodeActions
;
using
Microsoft.CodeAnalysis.Editing
;
using
Microsoft.CodeAnalysis.Editing
;
using
Microsoft.CodeAnalysis.Internal.Log
;
using
Microsoft.CodeAnalysis.Internal.Log
;
...
@@ -41,27 +42,20 @@ internal abstract class AbstractAddExplicitCastCodeFixProvider<
...
@@ -41,27 +42,20 @@ internal abstract class AbstractAddExplicitCastCodeFixProvider<
/// <summary>
/// <summary>
/// Given targetNode and conversionType, generate sub item name like "Cast to 'conversionType'"
/// Given targetNode and conversionType, generate sub item name like "Cast to 'conversionType'"
/// </summary>
/// </summary>
protected
abstract
string
GetSubItemName
(
CodeFixContext
context
,
SemanticModel
semanticModel
,
protected
abstract
string
GetSubItemName
(
CodeFixContext
context
,
SemanticModel
semanticModel
,
SyntaxNode
targetNode
,
ITypeSymbol
conversionType
);
SyntaxNode
targetNode
,
ITypeSymbol
conversionType
);
protected
abstract
SyntaxNode
ApplyFix
(
SyntaxNode
currentRoot
,
TExpressionSyntax
targetNode
,
protected
abstract
SyntaxNode
ApplyFix
(
SyntaxNode
currentRoot
,
TExpressionSyntax
targetNode
,
ITypeSymbol
conversionType
);
ITypeSymbol
conversionType
);
protected
abstract
CommonConversion
ClassifyConversion
(
SemanticModel
semanticModel
,
TExpressionSyntax
expression
,
ITypeSymbol
type
);
protected
abstract
CommonConversion
ClassifyConversion
(
SemanticModel
semanticModel
,
TExpressionSyntax
expression
,
ITypeSymbol
type
);
protected
abstract
SyntaxNode
GenerateNewArgument
(
SyntaxNode
oldArgument
,
ITypeSymbol
conversionType
);
protected
abstract
SyntaxNode
GenerateNewArgument
(
SyntaxNode
oldArgument
,
ITypeSymbol
conversionType
);
protected
abstract
SyntaxNode
GenerateNewArgumentList
(
SyntaxNode
oldArgumentList
,
List
<
SyntaxNode
>
newArguments
);
protected
abstract
SyntaxNode
GenerateNewArgumentList
(
protected
abstract
SymbolInfo
GetSpeculativeAttributeSymbolInfo
(
SemanticModel
semanticModel
,
int
position
,
TAttributeSyntax
attribute
);
SyntaxNode
oldArgumentList
,
List
<
SyntaxNode
>
newArguments
);
protected
abstract
SymbolInfo
GetSpeculativeAttributeSymbolInfo
(
SemanticModel
semanticModel
,
int
position
,
TAttributeSyntax
attribute
);
/// <summary>
/// <summary>
/// Output the current type information of the target node and the conversion type(s) that the target node is
/// Output the current type information of the target node and the conversion type(s) that the target node is
/// going to be cast by.
/// going to be cast by.
/// Implicit downcast can appear on Variable Declaration, Return Statement, Function Invocation, Attrbute
/// Implicit downcast can appear on Variable Declaration, Return Statement, Function Invocation, Attr
i
bute
/// <para/>
/// <para/>
/// For example:
/// For example:
/// Base b; Derived d = [||]b;
/// Base b; Derived d = [||]b;
...
@@ -97,9 +91,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
...
@@ -97,9 +91,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
semanticModel
,
root
,
diagnostic
.
Id
,
spanNode
,
cancellationToken
,
semanticModel
,
root
,
diagnostic
.
Id
,
spanNode
,
cancellationToken
,
out
var
potentialConversionTypes
);
out
var
potentialConversionTypes
);
if
(!
hasSolution
)
if
(!
hasSolution
)
{
return
;
return
;
}
if
(
potentialConversionTypes
.
Length
==
1
)
if
(
potentialConversionTypes
.
Length
==
1
)
{
{
...
@@ -107,41 +99,42 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
...
@@ -107,41 +99,42 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
FeaturesResources
.
Add_explicit_cast
,
FeaturesResources
.
Add_explicit_cast
,
c
=>
FixAsync
(
context
.
Document
,
context
.
Diagnostics
.
First
(),
c
)),
c
=>
FixAsync
(
context
.
Document
,
context
.
Diagnostics
.
First
(),
c
)),
context
.
Diagnostics
);
context
.
Diagnostics
);
return
;
}
}
else
using
var
_
=
ArrayBuilder
<
CodeAction
>.
GetInstance
(
out
var
actions
);
// MaximumConversionOptions: we show at most [MaximumConversionOptions] options for this code fixer
for
(
var
i
=
0
;
i
<
Math
.
Min
(
MaximumConversionOptions
,
potentialConversionTypes
.
Length
);
i
++)
{
{
var
actions
=
ArrayBuilder
<
CodeAction
>.
GetInstance
();
var
targetNode
=
potentialConversionTypes
[
i
].
node
;
var
conversionType
=
potentialConversionTypes
[
i
].
type
;
actions
.
Add
(
new
MyCodeAction
(
GetSubItemName
(
context
,
semanticModel
,
targetNode
,
conversionType
),
_
=>
Task
.
FromResult
(
document
.
WithSyntaxRoot
(
ApplyFix
(
root
,
targetNode
,
conversionType
)))));
}
// MaximumConversionOptions: we show at most [MaximumConversionOptions] options for this code fixer
ReportTelemetryIfNecessary
(
potentialConversionTypes
);
for
(
var
i
=
0
;
i
<
Math
.
Min
(
MaximumConversionOptions
,
potentialConversionTypes
.
Length
);
i
++)
{
var
targetNode
=
potentialConversionTypes
[
i
].
node
;
var
conversionType
=
potentialConversionTypes
[
i
].
type
;
actions
.
Add
(
new
MyCodeAction
(
GetSubItemName
(
context
,
semanticModel
,
targetNode
,
conversionType
),
_
=>
ApplySingleConversionToDocumentAsync
(
document
,
ApplyFix
(
root
,
targetNode
,
conversionType
))));
}
if
(
potentialConversionTypes
.
Length
>
MaximumConversionOptions
)
context
.
RegisterCodeFix
(
new
CodeAction
.
CodeActionWithNestedActions
(
{
FeaturesResources
.
Add_explicit_cast
,
// If the number of potential conversion types is larger than options we could show, report telemetry
actions
.
ToImmutable
(),
isInlinable
:
false
),
Logger
.
Log
(
FunctionId
.
CodeFixes_AddExplicitCast
,
context
.
Diagnostics
);
KeyValueLogMessage
.
Create
(
m
=>
}
{
m
[
"NumberOfCandidates"
]
=
potentialConversionTypes
.
Length
;
}));
}
context
.
RegisterCodeFix
(
new
CodeAction
.
CodeActionWithNestedActions
(
private
static
void
ReportTelemetryIfNecessary
(
ImmutableArray
<(
TExpressionSyntax
node
,
ITypeSymbol
type
)>
potentialConversionTypes
)
FeaturesResources
.
Add_explicit_cast
,
{
actions
.
ToImmutableAndFree
(),
isInlinable
:
false
),
if
(
potentialConversionTypes
.
Length
>
MaximumConversionOptions
)
context
.
Diagnostics
);
{
// If the number of potential conversion types is larger than options we could show, report telemetry
Logger
.
Log
(
FunctionId
.
CodeFixes_AddExplicitCast
,
KeyValueLogMessage
.
Create
(
m
=>
{
m
[
"NumberOfCandidates"
]
=
potentialConversionTypes
.
Length
;
}));
}
}
}
}
private
static
Task
<
Document
>
ApplySingleConversionToDocumentAsync
(
Document
document
,
SyntaxNode
currentRoot
)
=>
Task
.
FromResult
(
document
.
WithSyntaxRoot
(
currentRoot
));
protected
ImmutableArray
<(
TExpressionSyntax
,
ITypeSymbol
)>
FilterValidPotentialConversionTypes
(
protected
ImmutableArray
<(
TExpressionSyntax
,
ITypeSymbol
)>
FilterValidPotentialConversionTypes
(
ISyntaxFactsService
syntaxFacts
,
SemanticModel
semanticModel
,
ISyntaxFactsService
syntaxFacts
,
SemanticModel
semanticModel
,
ArrayBuilder
<(
TExpressionSyntax
node
,
ITypeSymbol
type
)>
mutablePotentialConversionTypes
)
ArrayBuilder
<(
TExpressionSyntax
node
,
ITypeSymbol
type
)>
mutablePotentialConversionTypes
)
...
@@ -164,6 +157,7 @@ private static Task<Document> ApplySingleConversionToDocumentAsync(Document docu
...
@@ -164,6 +157,7 @@ private static Task<Document> ApplySingleConversionToDocumentAsync(Document docu
validPotentialConversionTypes
.
Add
(
conversionTuple
);
validPotentialConversionTypes
.
Add
(
conversionTuple
);
}
}
return
validPotentialConversionTypes
.
Distinct
().
ToImmutableArray
();
return
validPotentialConversionTypes
.
Distinct
().
ToImmutableArray
();
}
}
...
@@ -232,8 +226,8 @@ private static Task<Document> ApplySingleConversionToDocumentAsync(Document docu
...
@@ -232,8 +226,8 @@ private static Task<Document> ApplySingleConversionToDocumentAsync(Document docu
newArguments
.
Add
(
arguments
[
i
]);
newArguments
.
Add
(
arguments
[
i
]);
continue
;
continue
;
}
}
var
parameterType
=
parameters
[
parameterIndex
].
Type
;
var
parameterType
=
parameters
[
parameterIndex
].
Type
;
if
(
parameters
[
parameterIndex
].
IsParams
if
(
parameters
[
parameterIndex
].
IsParams
&&
parameterType
is
IArrayTypeSymbol
paramsType
&&
parameterType
is
IArrayTypeSymbol
paramsType
&&
ClassifyConversion
(
semanticModel
,
argumentExpression
,
paramsType
.
ElementType
).
Exists
)
&&
ClassifyConversion
(
semanticModel
,
argumentExpression
,
paramsType
.
ElementType
).
Exists
)
...
@@ -255,8 +249,8 @@ private static Task<Document> ApplySingleConversionToDocumentAsync(Document docu
...
@@ -255,8 +249,8 @@ private static Task<Document> ApplySingleConversionToDocumentAsync(Document docu
// Direct conversion from a declaration expression to a type is unspecified, thus we classify the
// Direct conversion from a declaration expression to a type is unspecified, thus we classify the
// conversion from the type of declaration expression to the parameter type
// conversion from the type of declaration expression to the parameter type
// An example for this case:
// An example for this case:
// void
F
oo(out int i) { i = 1; }
// void
G
oo(out int i) { i = 1; }
//
F
oo([|out var i|]);
//
G
oo([|out var i|]);
// "var i" is a declaration expression
// "var i" is a declaration expression
//
//
// In addition, since this case is with keyword "out", the type of declaration expression and the
// In addition, since this case is with keyword "out", the type of declaration expression and the
...
@@ -280,7 +274,7 @@ private static Task<Document> ApplySingleConversionToDocumentAsync(Document docu
...
@@ -280,7 +274,7 @@ private static Task<Document> ApplySingleConversionToDocumentAsync(Document docu
/// <param name="newArguments"> new arguments that are cast by corresponding parameter types</param>
/// <param name="newArguments"> new arguments that are cast by corresponding parameter types</param>
/// <param name="targetNode"> The node needs to be cast.</param>
/// <param name="targetNode"> The node needs to be cast.</param>
/// <returns>
/// <returns>
/// Return true if the invocation expression with new arguments is applica
t
ble.
/// Return true if the invocation expression with new arguments is applicable.
/// Otherwise, return false
/// Otherwise, return false
/// </returns>
/// </returns>
protected
bool
IsInvocationExpressionWithNewArgumentsApplicable
(
protected
bool
IsInvocationExpressionWithNewArgumentsApplicable
(
...
@@ -382,7 +376,7 @@ private static Task<Document> ApplySingleConversionToDocumentAsync(Document docu
...
@@ -382,7 +376,7 @@ private static Task<Document> ApplySingleConversionToDocumentAsync(Document docu
{
{
// All diagnostics have the same error code
// All diagnostics have the same error code
if
(
TryGetTargetTypeInfo
(
document
,
semanticModel
,
currentRoot
,
diagnostics
[
0
].
Id
,
spanNode
,
if
(
TryGetTargetTypeInfo
(
document
,
semanticModel
,
currentRoot
,
diagnostics
[
0
].
Id
,
spanNode
,
cancellationToken
,
out
var
potentialConversionTypes
)
cancellationToken
,
out
var
potentialConversionTypes
)
&&
potentialConversionTypes
.
Length
==
1
)
&&
potentialConversionTypes
.
Length
==
1
)
{
{
return
ApplyFix
(
currentRoot
,
potentialConversionTypes
[
0
].
node
,
potentialConversionTypes
[
0
].
type
);
return
ApplyFix
(
currentRoot
,
potentialConversionTypes
[
0
].
node
,
potentialConversionTypes
[
0
].
type
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录