Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
499f27ad
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,发现更多精彩内容 >>
提交
499f27ad
编写于
5月 08, 2017
作者:
S
Sam Harwell
提交者:
GitHub
5月 08, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #18307 from sharwell/async-local-function
Fix support for local functions in "Make Method Asynchronous"
上级
911adf53
1bb2cbd2
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
399 addition
and
50 deletion
+399
-50
src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs
...ics/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs
+175
-0
src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodSynchronous/MakeMethodSynchronousTests.cs
...stics/MakeMethodSynchronous/MakeMethodSynchronousTests.cs
+107
-0
src/Features/CSharp/Portable/MakeMethodAsynchronous/CSharpMakeMethodAsynchronousCodeFixProvider.cs
...ynchronous/CSharpMakeMethodAsynchronousCodeFixProvider.cs
+34
-7
src/Features/CSharp/Portable/MakeMethodSynchronous/CSharpMakeMethodSynchronousCodeFixProvider.cs
...Synchronous/CSharpMakeMethodSynchronousCodeFixProvider.cs
+35
-17
src/Features/Core/Portable/MakeMethodAsynchronous/AbstractMakeMethodAsynchronousCodeFixProvider.cs
...chronous/AbstractMakeMethodAsynchronousCodeFixProvider.cs
+7
-9
src/Features/Core/Portable/MakeMethodSynchronous/AbstractMakeMethodSynchronousCodeFixProvider.cs
...nchronous/AbstractMakeMethodSynchronousCodeFixProvider.cs
+4
-3
src/Features/VisualBasic/Portable/MakeMethodAsynchronous/VisualBasicMakeMethodAsynchronousCodeFixProvider.vb
...onous/VisualBasicMakeMethodAsynchronousCodeFixProvider.vb
+2
-7
src/Features/VisualBasic/Portable/MakeMethodSynchronous/VisualBasicMakeMethodSynchronousCodeFixProvider.vb
...ronous/VisualBasicMakeMethodSynchronousCodeFixProvider.vb
+2
-7
src/Workspaces/CSharp/Portable/Extensions/SyntaxNodeExtensions.cs
...spaces/CSharp/Portable/Extensions/SyntaxNodeExtensions.cs
+7
-0
src/Workspaces/Core/Portable/Shared/Extensions/ISymbolExtensions.cs
...aces/Core/Portable/Shared/Extensions/ISymbolExtensions.cs
+11
-0
src/Workspaces/VisualBasic/Portable/Extensions/SyntaxNodeExtensions.vb
...s/VisualBasic/Portable/Extensions/SyntaxNodeExtensions.vb
+15
-0
未找到文件。
src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodAsynchronous/MakeMethodAsynchronousTests.cs
浏览文件 @
499f27ad
...
...
@@ -599,5 +599,180 @@ async ValueTask<int> TestAsync()
}"
;
await
TestInRegularAndScriptAsync
(
initial
,
expected
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsMakeMethodAsynchronous
)]
[
WorkItem
(
14133
,
"https://github.com/dotnet/roslyn/issues/14133"
)]
public
async
Task
AddAsyncInLocalFunction
()
{
await
TestInRegularAndScriptAsync
(
@"using System.Threading.Tasks;
class C
{
public void M1()
{
void M2()
{
[|await M3Async();|]
}
}
async Task<int> M3Async()
{
return 1;
}
}"
,
@"using System.Threading.Tasks;
class C
{
public void M1()
{
async Task M2Async()
{
await M3Async();
}
}
async Task<int> M3Async()
{
return 1;
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsMakeMethodAsynchronous
)]
[
WorkItem
(
14133
,
"https://github.com/dotnet/roslyn/issues/14133"
)]
public
async
Task
AddAsyncInLocalFunctionKeepVoidReturn
()
{
await
TestInRegularAndScriptAsync
(
@"using System.Threading.Tasks;
class C
{
public void M1()
{
void M2()
{
[|await M3Async();|]
}
}
async Task<int> M3Async()
{
return 1;
}
}"
,
@"using System.Threading.Tasks;
class C
{
public void M1()
{
async void M2Async()
{
await M3Async();
}
}
async Task<int> M3Async()
{
return 1;
}
}"
,
index
:
1
);
}
[
Theory
]
[
InlineData
(
0
,
"Task"
)]
[
InlineData
(
1
,
"void"
,
Skip
=
"https://github.com/dotnet/roslyn/issues/18396"
)]
[
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsMakeMethodAsynchronous
)]
[
WorkItem
(
18307
,
"https://github.com/dotnet/roslyn/issues/18307"
)]
public
async
Task
AddAsyncInLocalFunctionKeepsTrivia
(
int
codeFixIndex
,
string
expectedReturn
)
{
await
TestInRegularAndScriptAsync
(
@"using System.Threading.Tasks;
class C
{
public void M1()
{
// Leading trivia
/*1*/ void /*2*/ M2/*3*/() /*4*/
{
[|await M3Async();|]
}
}
async Task<int> M3Async()
{
return 1;
}
}"
,
$@"using System.Threading.Tasks;
class C
{{
public
void
M1
()
{{
// Leading trivia
/*1*/
async
{
expectedReturn
}
/*2*/
M2Async
/*3*/
()
/*4*/
{{
await
M3Async
();
}}
}}
async
Task
<
int
>
M3Async
()
{{
return
1
;
}}
}}
"
,
index
:
codeFixIndex
,
ignoreTrivia
:
false
);
}
[
Theory
]
[
InlineData
(
""
,
0
,
"Task"
)]
[
InlineData
(
""
,
1
,
"void"
,
Skip
=
"https://github.com/dotnet/roslyn/issues/18396"
)]
[
InlineData
(
"public"
,
0
,
"Task"
)]
[
InlineData
(
"public"
,
1
,
"void"
)]
[
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsMakeMethodAsynchronous
)]
[
WorkItem
(
18307
,
"https://github.com/dotnet/roslyn/issues/18307"
)]
public
async
Task
AddAsyncKeepsTrivia
(
string
modifiers
,
int
codeFixIndex
,
string
expectedReturn
)
{
await
TestInRegularAndScriptAsync
(
$@"using System.Threading.Tasks;
class C
{{
// Leading trivia
{
modifiers
}
/*1*/
void
/*2*/
M2
/*3*/
()
/*4*/
{{
[|
await
M3Async
();|]
}}
async
Task
<
int
>
M3Async
()
{{
return
1
;
}}
}}
"
,
$@"using System.Threading.Tasks;
class C
{{
// Leading trivia
{
modifiers
}
/*1*/
async
{
expectedReturn
}
/*2*/
M2Async
/*3*/
()
/*4*/
{{
await
M3Async
();
}}
async
Task
<
int
>
M3Async
()
{{
return
1
;
}}
}}
"
,
index
:
codeFixIndex
,
ignoreTrivia
:
false
);
}
}
}
\ No newline at end of file
src/EditorFeatures/CSharpTest/Diagnostics/MakeMethodSynchronous/MakeMethodSynchronousTests.cs
浏览文件 @
499f27ad
...
...
@@ -548,5 +548,112 @@ async void BarAsync()
}
}"
,
ignoreTrivia
:
false
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsMakeMethodAsynchronous
)]
[
WorkItem
(
14133
,
"https://github.com/dotnet/roslyn/issues/14133"
)]
public
async
Task
RemoveAsyncInLocalFunction
()
{
await
TestInRegularAndScriptAsync
(
@"using System.Threading.Tasks;
class C
{
public void M1()
{
async Task [|M2Async|]()
{
}
}
}"
,
@"using System.Threading.Tasks;
class C
{
public void M1()
{
void M2()
{
}
}
}"
);
}
[
Theory
]
[
InlineData
(
"Task<C>"
,
"C"
)]
[
InlineData
(
"Task<int>"
,
"int"
)]
[
InlineData
(
"Task"
,
"void"
)]
[
InlineData
(
"void"
,
"void"
)]
[
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsMakeMethodAsynchronous
)]
[
WorkItem
(
18307
,
"https://github.com/dotnet/roslyn/issues/18307"
)]
public
async
Task
RemoveAsyncInLocalFunctionKeepsTrivia
(
string
asyncReturn
,
string
expectedReturn
)
{
await
TestInRegularAndScriptAsync
(
$@"using System;
using System.Threading.Tasks;
class C
{{
public
void
M1
()
{{
// Leading trivia
/*1*/
async
{
asyncReturn
}
/*2*/
[|
M2Async
|]
/*3*/
()
/*4*/
{{
throw
new
NotImplementedException
();
}}
}}
}}
"
,
$@"using System;
using System.Threading.Tasks;
class C
{{
public
void
M1
()
{{
// Leading trivia
/*1*/
{
expectedReturn
}
/*2*/
M2
/*3*/
()
/*4*/
{{
throw
new
NotImplementedException
();
}}
}}
}}
"
);
}
[
Theory
]
[
InlineData
(
""
,
"Task<C>"
,
"C"
)]
[
InlineData
(
""
,
"Task<int>"
,
"int"
)]
[
InlineData
(
""
,
"Task"
,
"void"
)]
[
InlineData
(
""
,
"void"
,
"void"
)]
[
InlineData
(
"public"
,
"Task<C>"
,
"C"
)]
[
InlineData
(
"public"
,
"Task<int>"
,
"int"
)]
[
InlineData
(
"public"
,
"Task"
,
"void"
)]
[
InlineData
(
"public"
,
"void"
,
"void"
)]
[
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsMakeMethodAsynchronous
)]
[
WorkItem
(
18307
,
"https://github.com/dotnet/roslyn/issues/18307"
)]
public
async
Task
RemoveAsyncKeepsTrivia
(
string
modifiers
,
string
asyncReturn
,
string
expectedReturn
)
{
await
TestInRegularAndScriptAsync
(
$@"using System;
using System.Threading.Tasks;
class C
{{
// Leading trivia
{
modifiers
}
/*1*/
async
{
asyncReturn
}
/*2*/
[|
M2Async
|]
/*3*/
()
/*4*/
{{
throw
new
NotImplementedException
();
}}
}}
"
,
$@"using System;
using System.Threading.Tasks;
class C
{{
// Leading trivia
{
modifiers
}
/*1*/
{
expectedReturn
}
/*2*/
M2
/*3*/
()
/*4*/
{{
throw
new
NotImplementedException
();
}}
}}
"
);
}
}
}
\ No newline at end of file
src/Features/CSharp/Portable/MakeMethodAsynchronous/CSharpMakeMethodAsynchronousCodeFixProvider.cs
浏览文件 @
499f27ad
...
...
@@ -33,10 +33,8 @@ protected override string GetMakeAsyncVoidFunctionResource()
return
CSharpFeaturesResources
.
Make_method_async_remain_void
;
}
protected
override
bool
IsMethodOrAnonymousFunction
(
SyntaxNode
node
)
{
return
node
.
IsKind
(
SyntaxKind
.
MethodDeclaration
)
||
node
.
IsAnyLambdaOrAnonymousMethod
();
}
protected
override
bool
IsAsyncSupportingFunctionSyntax
(
SyntaxNode
node
)
=>
node
.
IsAsyncSupportingFunctionSyntax
();
protected
override
SyntaxNode
AddAsyncTokenAndFixReturnType
(
bool
keepVoid
,
IMethodSymbol
methodSymbolOpt
,
SyntaxNode
node
,
...
...
@@ -45,6 +43,7 @@ protected override bool IsMethodOrAnonymousFunction(SyntaxNode node)
switch
(
node
)
{
case
MethodDeclarationSyntax
method
:
return
FixMethod
(
keepVoid
,
methodSymbolOpt
,
method
,
taskType
,
taskOfTType
,
valueTaskOfTType
);
case
LocalFunctionStatementSyntax
localFunction
:
return
FixLocalFunction
(
keepVoid
,
methodSymbolOpt
,
localFunction
,
taskType
,
taskOfTType
,
valueTaskOfTType
);
case
AnonymousMethodExpressionSyntax
method
:
return
FixAnonymousMethod
(
method
);
case
ParenthesizedLambdaExpressionSyntax
lambda
:
return
FixParenthesizedLambda
(
lambda
);
case
SimpleLambdaExpressionSyntax
lambda
:
return
FixSimpleLambda
(
lambda
);
...
...
@@ -56,7 +55,25 @@ protected override bool IsMethodOrAnonymousFunction(SyntaxNode node)
bool
keepVoid
,
IMethodSymbol
methodSymbol
,
MethodDeclarationSyntax
method
,
INamedTypeSymbol
taskType
,
INamedTypeSymbol
taskOfTType
,
INamedTypeSymbol
valueTaskOfTType
)
{
var
newReturnType
=
method
.
ReturnType
;
var
newReturnType
=
FixMethodReturnType
(
keepVoid
,
methodSymbol
,
method
.
ReturnType
,
taskType
,
taskOfTType
,
valueTaskOfTType
);
var
newModifiers
=
AddAsyncModifierWithCorrectedTrivia
(
method
.
Modifiers
,
ref
newReturnType
);
return
method
.
WithReturnType
(
newReturnType
).
WithModifiers
(
newModifiers
);
}
private
SyntaxNode
FixLocalFunction
(
bool
keepVoid
,
IMethodSymbol
methodSymbol
,
LocalFunctionStatementSyntax
localFunction
,
INamedTypeSymbol
taskType
,
INamedTypeSymbol
taskOfTType
,
INamedTypeSymbol
valueTaskOfTType
)
{
var
newReturnType
=
FixMethodReturnType
(
keepVoid
,
methodSymbol
,
localFunction
.
ReturnType
,
taskType
,
taskOfTType
,
valueTaskOfTType
);
var
newModifiers
=
AddAsyncModifierWithCorrectedTrivia
(
localFunction
.
Modifiers
,
ref
newReturnType
);
return
localFunction
.
WithReturnType
(
newReturnType
).
WithModifiers
(
newModifiers
);
}
private
static
TypeSyntax
FixMethodReturnType
(
bool
keepVoid
,
IMethodSymbol
methodSymbol
,
TypeSyntax
returnType
,
INamedTypeSymbol
taskType
,
INamedTypeSymbol
taskOfTType
,
INamedTypeSymbol
valueTaskOfTType
)
{
var
newReturnType
=
returnType
;
if
(
methodSymbol
.
ReturnsVoid
)
{
...
...
@@ -75,8 +92,18 @@ protected override bool IsMethodOrAnonymousFunction(SyntaxNode node)
}
}
var
newModifiers
=
method
.
Modifiers
.
Add
(
s_asyncToken
);
return
method
.
WithReturnType
(
newReturnType
).
WithModifiers
(
newModifiers
);
return
newReturnType
.
WithTriviaFrom
(
returnType
);
}
private
static
SyntaxTokenList
AddAsyncModifierWithCorrectedTrivia
(
SyntaxTokenList
modifiers
,
ref
TypeSyntax
newReturnType
)
{
if
(
modifiers
.
Any
())
return
modifiers
.
Add
(
s_asyncToken
);
// Move the leading trivia from the return type to the new modifiers list.
SyntaxTokenList
result
=
SyntaxFactory
.
TokenList
(
s_asyncToken
.
WithLeadingTrivia
(
newReturnType
.
GetLeadingTrivia
()));
newReturnType
=
newReturnType
.
WithoutLeadingTrivia
();
return
result
;
}
private
SyntaxNode
FixParenthesizedLambda
(
ParenthesizedLambdaExpressionSyntax
lambda
)
...
...
src/Features/CSharp/Portable/MakeMethodSynchronous/CSharpMakeMethodSynchronousCodeFixProvider.cs
浏览文件 @
499f27ad
...
...
@@ -17,16 +17,15 @@ internal class CSharpMakeMethodSynchronousCodeFixProvider : AbstractMakeMethodSy
public
override
ImmutableArray
<
string
>
FixableDiagnosticIds
{
get
;
}
=
ImmutableArray
.
Create
(
CS1998
);
protected
override
bool
IsMethodOrAnonymousFunction
(
SyntaxNode
node
)
{
return
node
.
IsKind
(
SyntaxKind
.
MethodDeclaration
)
||
node
.
IsAnyLambdaOrAnonymousMethod
();
}
protected
override
bool
IsAsyncSupportingFunctionSyntax
(
SyntaxNode
node
)
=>
node
.
IsAsyncSupportingFunctionSyntax
();
protected
override
SyntaxNode
RemoveAsyncTokenAndFixReturnType
(
IMethodSymbol
methodSymbolOpt
,
SyntaxNode
node
,
ITypeSymbol
taskType
,
ITypeSymbol
taskOfTType
)
{
switch
(
node
)
{
case
MethodDeclarationSyntax
method
:
return
FixMethod
(
methodSymbolOpt
,
method
,
taskType
,
taskOfTType
);
case
LocalFunctionStatementSyntax
localFunction
:
return
FixLocalFunction
(
methodSymbolOpt
,
localFunction
,
taskType
,
taskOfTType
);
case
AnonymousMethodExpressionSyntax
method
:
return
FixAnonymousMethod
(
method
);
case
ParenthesizedLambdaExpressionSyntax
lambda
:
return
FixParenthesizedLambda
(
lambda
);
case
SimpleLambdaExpressionSyntax
lambda
:
return
FixSimpleLambda
(
lambda
);
...
...
@@ -36,47 +35,66 @@ protected override SyntaxNode RemoveAsyncTokenAndFixReturnType(IMethodSymbol met
private
SyntaxNode
FixMethod
(
IMethodSymbol
methodSymbol
,
MethodDeclarationSyntax
method
,
ITypeSymbol
taskType
,
ITypeSymbol
taskOfTType
)
{
var
newReturnType
=
method
.
ReturnType
;
var
newReturnType
=
FixMethodReturnType
(
methodSymbol
,
method
.
ReturnType
,
taskType
,
taskOfTType
);
var
newModifiers
=
FixMethodModifiers
(
method
.
Modifiers
,
ref
newReturnType
);
return
method
.
WithReturnType
(
newReturnType
).
WithModifiers
(
newModifiers
);
}
private
SyntaxNode
FixLocalFunction
(
IMethodSymbol
methodSymbol
,
LocalFunctionStatementSyntax
localFunction
,
ITypeSymbol
taskType
,
ITypeSymbol
taskOfTType
)
{
var
newReturnType
=
FixMethodReturnType
(
methodSymbol
,
localFunction
.
ReturnType
,
taskType
,
taskOfTType
);
var
newModifiers
=
FixMethodModifiers
(
localFunction
.
Modifiers
,
ref
newReturnType
);
return
localFunction
.
WithReturnType
(
newReturnType
).
WithModifiers
(
newModifiers
);
}
private
static
TypeSyntax
FixMethodReturnType
(
IMethodSymbol
methodSymbol
,
TypeSyntax
returnType
,
ITypeSymbol
taskType
,
ITypeSymbol
taskOfTType
)
{
var
newReturnType
=
returnType
;
// If the return type is Task<T>, then make the new return type "T".
// If it is Task, then make the new return type "void".
if
(
methodSymbol
.
ReturnType
.
OriginalDefinition
.
Equals
(
taskType
))
{
newReturnType
=
SyntaxFactory
.
PredefinedType
(
SyntaxFactory
.
Token
(
SyntaxKind
.
VoidKeyword
)).
WithTriviaFrom
(
method
.
R
eturnType
);
newReturnType
=
SyntaxFactory
.
PredefinedType
(
SyntaxFactory
.
Token
(
SyntaxKind
.
VoidKeyword
)).
WithTriviaFrom
(
r
eturnType
);
}
else
if
(
methodSymbol
.
ReturnType
.
OriginalDefinition
.
Equals
(
taskOfTType
))
{
newReturnType
=
methodSymbol
.
ReturnType
.
GetTypeArguments
()[
0
].
GenerateTypeSyntax
().
WithTriviaFrom
(
method
.
R
eturnType
);
newReturnType
=
methodSymbol
.
ReturnType
.
GetTypeArguments
()[
0
].
GenerateTypeSyntax
().
WithTriviaFrom
(
r
eturnType
);
}
var
asyncTokenIndex
=
method
.
Modifiers
.
IndexOf
(
SyntaxKind
.
AsyncKeyword
);
return
newReturnType
;
}
private
static
SyntaxTokenList
FixMethodModifiers
(
SyntaxTokenList
modifiers
,
ref
TypeSyntax
newReturnType
)
{
var
asyncTokenIndex
=
modifiers
.
IndexOf
(
SyntaxKind
.
AsyncKeyword
);
SyntaxTokenList
newModifiers
;
if
(
asyncTokenIndex
==
0
)
{
// Have to move the trivia on t
eh
async token appropriately.
var
asyncLeadingTrivia
=
m
ethod
.
M
odifiers
[
0
].
LeadingTrivia
;
// Have to move the trivia on t
he
async token appropriately.
var
asyncLeadingTrivia
=
modifiers
[
0
].
LeadingTrivia
;
if
(
m
ethod
.
M
odifiers
.
Count
>
1
)
if
(
modifiers
.
Count
>
1
)
{
// Move the trivia to the next modifier;
newModifiers
=
m
ethod
.
M
odifiers
.
Replace
(
m
ethod
.
M
odifiers
[
1
],
m
ethod
.
M
odifiers
[
1
].
WithPrependedLeadingTrivia
(
asyncLeadingTrivia
));
newModifiers
=
modifiers
.
Replace
(
modifiers
[
1
],
modifiers
[
1
].
WithPrependedLeadingTrivia
(
asyncLeadingTrivia
));
newModifiers
=
newModifiers
.
RemoveAt
(
0
);
}
else
{
// move it to the return type.
newModifiers
=
m
ethod
.
M
odifiers
.
RemoveAt
(
0
);
newModifiers
=
modifiers
.
RemoveAt
(
0
);
newReturnType
=
newReturnType
.
WithPrependedLeadingTrivia
(
asyncLeadingTrivia
);
}
}
else
{
newModifiers
=
m
ethod
.
M
odifiers
.
RemoveAt
(
asyncTokenIndex
);
newModifiers
=
modifiers
.
RemoveAt
(
asyncTokenIndex
);
}
return
method
.
WithReturnType
(
newReturnType
).
WithModifiers
(
newModifiers
)
;
return
newModifiers
;
}
private
SyntaxNode
FixParenthesizedLambda
(
ParenthesizedLambdaExpressionSyntax
lambda
)
...
...
src/Features/Core/Portable/MakeMethodAsynchronous/AbstractMakeMethodAsynchronousCodeFixProvider.cs
浏览文件 @
499f27ad
...
...
@@ -6,7 +6,6 @@
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.CodeActions
;
using
Microsoft.CodeAnalysis.CodeFixes
;
using
Microsoft.CodeAnalysis.Formatting
;
using
Microsoft.CodeAnalysis.Rename
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Roslyn.Utilities
;
...
...
@@ -15,7 +14,7 @@ namespace Microsoft.CodeAnalysis.MakeMethodAsynchronous
{
internal
abstract
class
AbstractMakeMethodAsynchronousCodeFixProvider
:
CodeFixProvider
{
protected
abstract
bool
Is
MethodOrAnonymousFunction
(
SyntaxNode
node
);
protected
abstract
bool
Is
AsyncSupportingFunctionSyntax
(
SyntaxNode
node
);
protected
abstract
SyntaxNode
AddAsyncTokenAndFixReturnType
(
bool
keepVoid
,
IMethodSymbol
methodSymbolOpt
,
SyntaxNode
node
,
INamedTypeSymbol
taskType
,
INamedTypeSymbol
taskOfTType
,
INamedTypeSymbol
valueTaskOfTType
);
...
...
@@ -51,8 +50,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
// If it's a void returning method, offer to keep the void return type, or convert to
// a Task return type.
if
(
symbol
?.
MethodKind
==
MethodKind
.
Ordinary
&&
symbol
.
ReturnsVoid
)
bool
isOrdinaryOrLocalFunction
=
symbol
.
IsOrdinaryMethodOrLocalFunction
();
if
(
isOrdinaryOrLocalFunction
&&
symbol
.
ReturnsVoid
)
{
context
.
RegisterCodeFix
(
new
MyCodeAction
(
GetMakeAsyncTaskFunctionResource
(),
c
=>
FixNodeAsync
(
...
...
@@ -100,8 +99,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
var
semanticModel
=
await
document
.
GetSemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
methodSymbolOpt
=
semanticModel
.
GetDeclaredSymbol
(
node
)
as
IMethodSymbol
;
if
(
methodSymbolOpt
?.
MethodKind
==
MethodKind
.
Ordinary
&&
!
methodSymbolOpt
.
Name
.
EndsWith
(
AsyncSuffix
))
bool
isOrdinaryOrLocalFunction
=
methodSymbolOpt
.
IsOrdinaryMethodOrLocalFunction
();
if
(
isOrdinaryOrLocalFunction
&&
!
methodSymbolOpt
.
Name
.
EndsWith
(
AsyncSuffix
))
{
return
await
RenameThenAddAsyncTokenAsync
(
keepVoid
,
document
,
node
,
methodSymbolOpt
,
cancellationToken
).
ConfigureAwait
(
false
);
...
...
@@ -116,7 +115,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
private
SyntaxNode
GetContainingFunction
(
Diagnostic
diagnostic
,
CancellationToken
cancellationToken
)
{
var
token
=
diagnostic
.
Location
.
FindToken
(
cancellationToken
);
var
node
=
token
.
GetAncestor
(
Is
MethodOrAnonymousFunction
);
var
node
=
token
.
GetAncestor
(
Is
AsyncSupportingFunctionSyntax
);
return
node
;
}
...
...
@@ -152,8 +151,7 @@ private SyntaxNode GetContainingFunction(Diagnostic diagnostic, CancellationToke
var
compilation
=
await
document
.
Project
.
GetCompilationAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
(
taskType
,
taskOfTType
,
valueTaskOfTType
)
=
GetTaskTypes
(
compilation
);
var
newNode
=
AddAsyncTokenAndFixReturnType
(
keepVoid
,
methodSymbolOpt
,
node
,
taskType
,
taskOfTType
,
valueTaskOfTType
)
.
WithAdditionalAnnotations
(
Formatter
.
Annotation
);
var
newNode
=
AddAsyncTokenAndFixReturnType
(
keepVoid
,
methodSymbolOpt
,
node
,
taskType
,
taskOfTType
,
valueTaskOfTType
);
var
root
=
await
document
.
GetSyntaxRootAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
newRoot
=
root
.
ReplaceNode
(
node
,
newNode
);
...
...
src/Features/Core/Portable/MakeMethodSynchronous/AbstractMakeMethodSynchronousCodeFixProvider.cs
浏览文件 @
499f27ad
...
...
@@ -22,7 +22,7 @@ internal abstract class AbstractMakeMethodSynchronousCodeFixProvider : CodeFixPr
{
public
static
readonly
string
EquivalenceKey
=
FeaturesResources
.
Make_method_synchronous
;
protected
abstract
bool
Is
MethodOrAnonymousFunction
(
SyntaxNode
node
);
protected
abstract
bool
Is
AsyncSupportingFunctionSyntax
(
SyntaxNode
node
);
protected
abstract
SyntaxNode
RemoveAsyncTokenAndFixReturnType
(
IMethodSymbol
methodSymbolOpt
,
SyntaxNode
node
,
ITypeSymbol
taskType
,
ITypeSymbol
taskOfTType
);
public
override
FixAllProvider
GetFixAllProvider
()
=>
WellKnownFixAllProviders
.
BatchFixer
;
...
...
@@ -41,7 +41,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
Document
document
,
Diagnostic
diagnostic
,
CancellationToken
cancellationToken
)
{
var
token
=
diagnostic
.
Location
.
FindToken
(
cancellationToken
);
var
node
=
token
.
GetAncestor
(
Is
MethodOrAnonymousFunction
);
var
node
=
token
.
GetAncestor
(
Is
AsyncSupportingFunctionSyntax
);
// See if we're on an actual method declaration (otherwise we're on a lambda declaration).
// If we're on a method declaration, we'll get an IMethodSymbol back. In that case, check
...
...
@@ -49,7 +49,8 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
var
semanticModel
=
await
document
.
GetSemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
methodSymbolOpt
=
semanticModel
.
GetDeclaredSymbol
(
node
)
as
IMethodSymbol
;
if
(
methodSymbolOpt
?.
MethodKind
==
MethodKind
.
Ordinary
&&
bool
isOrdinaryOrLocalFunction
=
methodSymbolOpt
.
IsOrdinaryMethodOrLocalFunction
();
if
(
isOrdinaryOrLocalFunction
&&
methodSymbolOpt
.
Name
.
Length
>
AsyncSuffix
.
Length
&&
methodSymbolOpt
.
Name
.
EndsWith
(
AsyncSuffix
))
{
...
...
src/Features/VisualBasic/Portable/MakeMethodAsynchronous/VisualBasicMakeMethodAsynchronousCodeFixProvider.vb
浏览文件 @
499f27ad
...
...
@@ -35,13 +35,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.MakeMethodAsynchronous
Return
VBFeaturesResources
.
Make_Async_Sub
End
Function
Protected
Overrides
Function
IsMethodOrAnonymousFunction
(
node
As
SyntaxNode
)
As
Boolean
Return
node
.
IsKind
(
SyntaxKind
.
FunctionBlock
)
OrElse
node
.
IsKind
(
SyntaxKind
.
SubBlock
)
OrElse
node
.
IsKind
(
SyntaxKind
.
MultiLineFunctionLambdaExpression
)
OrElse
node
.
IsKind
(
SyntaxKind
.
MultiLineSubLambdaExpression
)
OrElse
node
.
IsKind
(
SyntaxKind
.
SingleLineFunctionLambdaExpression
)
OrElse
node
.
IsKind
(
SyntaxKind
.
SingleLineSubLambdaExpression
)
Protected
Overrides
Function
IsAsyncSupportingFunctionSyntax
(
node
As
SyntaxNode
)
As
Boolean
Return
node
.
IsAsyncSupportedFunctionSyntax
()
End
Function
Protected
Overrides
Function
AddAsyncTokenAndFixReturnType
(
...
...
src/Features/VisualBasic/Portable/MakeMethodSynchronous/VisualBasicMakeMethodSynchronousCodeFixProvider.vb
浏览文件 @
499f27ad
...
...
@@ -21,13 +21,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.MakeMethodSynchronous
End
Get
End
Property
Protected
Overrides
Function
IsMethodOrAnonymousFunction
(
node
As
SyntaxNode
)
As
Boolean
Return
node
.
IsKind
(
SyntaxKind
.
FunctionBlock
)
OrElse
node
.
IsKind
(
SyntaxKind
.
SubBlock
)
OrElse
node
.
IsKind
(
SyntaxKind
.
MultiLineFunctionLambdaExpression
)
OrElse
node
.
IsKind
(
SyntaxKind
.
MultiLineSubLambdaExpression
)
OrElse
node
.
IsKind
(
SyntaxKind
.
SingleLineFunctionLambdaExpression
)
OrElse
node
.
IsKind
(
SyntaxKind
.
SingleLineSubLambdaExpression
)
Protected
Overrides
Function
IsAsyncSupportingFunctionSyntax
(
node
As
SyntaxNode
)
As
Boolean
Return
node
.
IsAsyncSupportedFunctionSyntax
()
End
Function
Protected
Overrides
Function
RemoveAsyncTokenAndFixReturnType
(
methodSymbolOpt
As
IMethodSymbol
,
node
As
SyntaxNode
,
taskType
As
ITypeSymbol
,
taskOfTType
As
ITypeSymbol
)
As
SyntaxNode
...
...
src/Workspaces/CSharp/Portable/Extensions/SyntaxNodeExtensions.cs
浏览文件 @
499f27ad
...
...
@@ -295,6 +295,13 @@ public static TNode ConvertToSingleLine<TNode>(this TNode node, bool useElasticT
return
(
TNode
)
rewriter
.
Visit
(
node
);
}
public
static
bool
IsAsyncSupportingFunctionSyntax
(
this
SyntaxNode
node
)
{
return
node
.
IsKind
(
SyntaxKind
.
MethodDeclaration
)
||
node
.
IsAnyLambdaOrAnonymousMethod
()
||
node
.
IsKind
(
SyntaxKind
.
LocalFunctionStatement
);
}
public
static
bool
IsAnyArgumentList
(
this
SyntaxNode
node
)
{
return
node
.
IsKind
(
SyntaxKind
.
ArgumentList
)
||
...
...
src/Workspaces/Core/Portable/Shared/Extensions/ISymbolExtensions.cs
浏览文件 @
499f27ad
...
...
@@ -253,6 +253,17 @@ public static bool IsOrdinaryMethod(this ISymbol symbol)
return
(
symbol
as
IMethodSymbol
)?.
MethodKind
==
MethodKind
.
Ordinary
;
}
public
static
bool
IsOrdinaryMethodOrLocalFunction
(
this
ISymbol
symbol
)
{
if
(!(
symbol
is
IMethodSymbol
method
))
{
return
false
;
}
return
method
.
MethodKind
==
MethodKind
.
Ordinary
||
method
.
MethodKind
==
MethodKind
.
LocalFunction
;
}
public
static
bool
IsDelegateType
(
this
ISymbol
symbol
)
{
return
symbol
is
ITypeSymbol
&&
((
ITypeSymbol
)
symbol
).
TypeKind
==
TypeKind
.
Delegate
;
...
...
src/Workspaces/VisualBasic/Portable/Extensions/SyntaxNodeExtensions.vb
浏览文件 @
499f27ad
...
...
@@ -188,6 +188,21 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Return
Contract
.
FailWithReturn
(
Of
SyntaxList
(
Of
StatementSyntax
))(
"unknown statements container!"
)
End
Function
<
Extension
()
>
Friend
Function
IsAsyncSupportedFunctionSyntax
(
node
As
SyntaxNode
)
As
Boolean
Select
Case
node
?
.
Kind
()
Case
_
SyntaxKind
.
FunctionBlock
,
SyntaxKind
.
SubBlock
,
SyntaxKind
.
MultiLineFunctionLambdaExpression
,
SyntaxKind
.
MultiLineSubLambdaExpression
,
SyntaxKind
.
SingleLineFunctionLambdaExpression
,
SyntaxKind
.
SingleLineSubLambdaExpression
Return
True
End
Select
Return
False
End
Function
<
Extension
()
>
Friend
Function
IsMultiLineLambda
(
node
As
SyntaxNode
)
As
Boolean
Return
SyntaxFacts
.
IsMultiLineLambdaExpression
(
node
.
Kind
())
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录