Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
adf8298e
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,发现更多精彩内容 >>
提交
adf8298e
编写于
11月 21, 2017
作者:
V
Victor Z
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixed reivew notes.
上级
45cb3c46
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
212 addition
and
45 deletion
+212
-45
src/EditorFeatures/CSharpTest/UseLocalFunction/UseLocalFunctionTests.cs
...ures/CSharpTest/UseLocalFunction/UseLocalFunctionTests.cs
+186
-8
src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionCodeFixProvider.cs
...UseLocalFunction/CSharpUseLocalFunctionCodeFixProvider.cs
+18
-26
src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionDiagnosticAnalyzer.cs
...LocalFunction/CSharpUseLocalFunctionDiagnosticAnalyzer.cs
+8
-11
未找到文件。
src/EditorFeatures/CSharpTest/UseLocalFunction/UseLocalFunctionTests.cs
浏览文件 @
adf8298e
...
...
@@ -1436,10 +1436,10 @@ public void Caller()
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseLocalFunction
)]
[
WorkItem
(
2
3150
,
"https://github.com/dotnet/roslyn/issues/23150
"
)]
public
async
Task
Test
WithInvokeMethod
()
[
WorkItem
(
2
2672
,
"https://github.com/dotnet/roslyn/issues/22672
"
)]
public
async
Task
Test
MissingIfUsedInMemberAccess1
()
{
await
Test
InRegularAndScript1
Async
(
await
Test
Missing
Async
(
@"using System;
class Enclosing<T> where T : class
...
...
@@ -1452,10 +1452,17 @@ public void Caller()
{
MyDelegate [||]local = x => x;
local.Invoke
();
var str = local.ToString
();
}
}
}"
,
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseLocalFunction
)]
[
WorkItem
(
23150
,
"https://github.com/dotnet/roslyn/issues/23150"
)]
public
async
Task
TestMissingIfUsedInMemberAccess2
()
{
await
TestMissingAsync
(
@"using System;
class Enclosing<T> where T : class
...
...
@@ -1464,11 +1471,14 @@ class Enclosing<T> where T : class
public class Class
{
public void Caller()
public void Caller(
T t
)
{
T local(T x = null)
=> x;
MyDelegate[||]local = x
=> x;
local();
Console.Write(local.Invoke(t));
var str = local.ToString();
local.Invoke(t);
}
}
}"
);
...
...
@@ -1495,6 +1505,174 @@ public void Caller()
Expression<Action> expression = () => local(null);
}
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseLocalFunction
)]
[
WorkItem
(
23150
,
"https://github.com/dotnet/roslyn/issues/23150"
)]
public
async
Task
TestWithInvokeMethod1
()
{
await
TestInRegularAndScript1Async
(
@"using System;
class Enclosing<T> where T : class
{
delegate T MyDelegate(T t = null);
public class Class
{
public void Caller()
{
MyDelegate [||]local = x => x;
local.Invoke();
}
}
}"
,
@"using System;
class Enclosing<T> where T : class
{
delegate T MyDelegate(T t = null);
public class Class
{
public void Caller()
{
T local(T x = null) => x;
local();
}
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseLocalFunction
)]
[
WorkItem
(
23150
,
"https://github.com/dotnet/roslyn/issues/23150"
)]
public
async
Task
TestWithInvokeMethod2
()
{
await
TestInRegularAndScript1Async
(
@"using System;
class Enclosing<T> where T : class
{
delegate T MyDelegate(T t = null);
public class Class
{
public void Caller(T t)
{
MyDelegate [||]local = x => x;
Console.Write(local.Invoke(t));
}
}
}"
,
@"using System;
class Enclosing<T> where T : class
{
delegate T MyDelegate(T t = null);
public class Class
{
public void Caller(T t)
{
T local(T x = null) => x;
Console.Write(local(t));
}
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseLocalFunction
)]
[
WorkItem
(
23150
,
"https://github.com/dotnet/roslyn/issues/23150"
)]
public
async
Task
TestWithInvokeMethod3
()
{
await
TestInRegularAndScript1Async
(
@"using System;
class Enclosing<T> where T : class
{
delegate T MyDelegate(T t = null);
public class Class
{
public void Caller(T t)
{
MyDelegate [||]local = x => x;
Console.Write(local.Invoke(t));
var val = local.Invoke(t);
local.Invoke(t);
}
}
}"
,
@"using System;
class Enclosing<T> where T : class
{
delegate T MyDelegate(T t = null);
public class Class
{
public void Caller(T t)
{
T local(T x = null) => x;
Console.Write(local(t));
var val = local(t);
local(t);
}
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseLocalFunction
)]
[
WorkItem
(
23150
,
"https://github.com/dotnet/roslyn/issues/23150"
)]
public
async
Task
TestWithInvokeMethod4
()
{
await
TestInRegularAndScript1Async
(
@"using System;
class Enclosing<T> where T : class
{
delegate T MyDelegate(T t = null);
public class Class
{
public void Caller(T t)
{
MyDelegate [||]local = x => x;
Console.Write(local.Invoke(t));
var val = local.Invoke(t);
local(t);
}
}
}"
,
@"using System;
class Enclosing<T> where T : class
{
delegate T MyDelegate(T t = null);
public class Class
{
public void Caller(T t)
{
T local(T x = null) => x;
Console.Write(local(t));
var val = local(t);
local(t);
}
}
}"
);
}
}
...
...
src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionCodeFixProvider.cs
浏览文件 @
adf8298e
...
...
@@ -48,7 +48,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
var
localDeclarationToLambda
=
new
Dictionary
<
LocalDeclarationStatementSyntax
,
LambdaExpressionSyntax
>();
var
nodesToTrack
=
new
HashSet
<
SyntaxNode
>();
var
memberAcces
s
=
new
List
<
MemberAccessExpressionSyntax
>();
var
explicitInvokeCall
s
=
new
List
<
MemberAccessExpressionSyntax
>();
foreach
(
var
diagnostic
in
diagnostics
)
{
var
localDeclaration
=
(
LocalDeclarationStatementSyntax
)
diagnostic
.
AdditionalLocations
[
0
].
FindNode
(
cancellationToken
);
...
...
@@ -59,16 +59,13 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
nodesToTrack
.
Add
(
localDeclaration
);
nodesToTrack
.
Add
(
lambda
);
if
(
diagnostic
.
AdditionalLocations
.
Count
>
2
)
for
(
var
i
=
2
;
i
<
diagnostic
.
AdditionalLocations
.
Count
;
i
++
)
{
for
(
var
i
=
2
;
i
<
diagnostic
.
AdditionalLocations
.
Count
;
i
++)
{
memberAccess
.
Add
((
MemberAccessExpressionSyntax
)
diagnostic
.
AdditionalLocations
[
i
].
FindNode
(
cancellationToken
));
}
explicitInvokeCalls
.
Add
((
MemberAccessExpressionSyntax
)
diagnostic
.
AdditionalLocations
[
i
].
FindNode
(
getInnermostNodeForTie
:
true
,
cancellationToken
));
}
}
nodesToTrack
.
AddRange
(
memberAcces
s
);
nodesToTrack
.
AddRange
(
explicitInvokeCall
s
);
var
root
=
editor
.
OriginalRoot
;
var
currentRoot
=
root
.
TrackNodes
(
nodesToTrack
);
...
...
@@ -85,7 +82,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
currentRoot
=
ReplaceAnonymousWithLocalFunction
(
document
.
Project
.
Solution
.
Workspace
,
currentRoot
,
currentLocalDeclaration
,
currentLambda
,
delegateType
,
parameterList
,
memberAcces
s
.
Select
(
node
=>
currentRoot
.
GetCurrentNode
(
node
)).
ToImmutableArray
(),
delegateType
,
parameterList
,
explicitInvokeCall
s
.
Select
(
node
=>
currentRoot
.
GetCurrentNode
(
node
)).
ToImmutableArray
(),
cancellationToken
);
}
...
...
@@ -96,7 +93,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
Workspace
workspace
,
SyntaxNode
currentRoot
,
LocalDeclarationStatementSyntax
localDeclaration
,
LambdaExpressionSyntax
lambda
,
INamedTypeSymbol
delegateType
,
ParameterListSyntax
parameterList
,
ImmutableArray
<
MemberAccessExpressionSyntax
>
notDirectInvocationUsage
s
,
ImmutableArray
<
MemberAccessExpressionSyntax
>
explicitInvokeCall
s
,
CancellationToken
cancellationToken
)
{
var
newLocalFunctionStatement
=
CreateLocalFunctionStatement
(
...
...
@@ -116,14 +113,11 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
editor
.
RemoveNode
(
lambdaStatement
);
}
if
(!
notDirectInvocationUsages
.
IsEmpty
)
foreach
(
var
usage
in
explicitInvokeCalls
)
{
foreach
(
var
usage
in
notDirectInvocationUsages
)
{
editor
.
ReplaceNode
(
usage
.
Parent
,
SyntaxFactory
.
InvocationExpression
(
usage
.
Expression
,
(
usage
.
Parent
as
InvocationExpressionSyntax
).
ArgumentList
));
}
editor
.
ReplaceNode
(
usage
.
Parent
,
(
usage
.
Parent
as
InvocationExpressionSyntax
).
WithExpression
(
usage
.
Expression
).
WithTriviaFrom
(
usage
.
Parent
));
}
return
editor
.
GetChangedRoot
();
...
...
@@ -166,27 +160,27 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
}
private
ParameterListSyntax
GenerateParameterList
(
SemanticModel
semanticModel
,
AnonymousFunctionExpressionSyntax
anonymousFunction
,
INamedTypeSymbol
namedTypeSymbol
,
CancellationToken
cancellationToken
)
SemanticModel
semanticModel
,
AnonymousFunctionExpressionSyntax
anonymousFunction
,
INamedTypeSymbol
delegateType
,
CancellationToken
cancellationToken
)
{
switch
(
anonymousFunction
)
{
case
SimpleLambdaExpressionSyntax
simpleLambda
:
return
GenerateSimpleLambdaParameterList
(
semanticModel
,
simpleLambda
,
namedTypeSymbol
,
cancellationToken
);
return
GenerateSimpleLambdaParameterList
(
semanticModel
,
simpleLambda
,
delegateType
.
DelegateInvokeMethod
,
cancellationToken
);
case
ParenthesizedLambdaExpressionSyntax
parenthesizedLambda
:
return
GenerateParenthesizedLambdaParameterList
(
semanticModel
,
parenthesizedLambda
,
namedTypeSymbol
,
cancellationToken
);
return
GenerateParenthesizedLambdaParameterList
(
semanticModel
,
parenthesizedLambda
,
delegateType
.
DelegateInvokeMethod
,
cancellationToken
);
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
anonymousFunction
);
}
}
private
ParameterListSyntax
GenerateSimpleLambdaParameterList
(
SemanticModel
semanticModel
,
SimpleLambdaExpressionSyntax
lambdaExpression
,
I
NamedTypeSymbol
namedTypeSymbol
,
CancellationToken
cancellationToken
)
SemanticModel
semanticModel
,
SimpleLambdaExpressionSyntax
lambdaExpression
,
I
MethodSymbol
delegateInvokeMethod
,
CancellationToken
cancellationToken
)
{
var
parameter
=
semanticModel
.
GetDeclaredSymbol
(
lambdaExpression
.
Parameter
,
cancellationToken
);
var
type
=
parameter
?.
Type
.
GenerateTypeSyntax
()
??
s_objectType
;
var
parameterSyntax
=
SyntaxFactory
.
Parameter
(
lambdaExpression
.
Parameter
.
Identifier
).
WithType
(
type
);
var
param
=
namedTypeSymbol
.
D
elegateInvokeMethod
.
Parameters
[
0
];
var
param
=
d
elegateInvokeMethod
.
Parameters
[
0
];
if
(
param
.
HasExplicitDefaultValue
)
{
parameterSyntax
=
parameterSyntax
.
WithDefault
(
GetDefaultValue
(
param
));
...
...
@@ -197,7 +191,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
}
private
ParameterListSyntax
GenerateParenthesizedLambdaParameterList
(
SemanticModel
semanticModel
,
ParenthesizedLambdaExpressionSyntax
lambdaExpression
,
I
NamedTypeSymbol
namedTypeSymbol
,
CancellationToken
cancellationToken
)
SemanticModel
semanticModel
,
ParenthesizedLambdaExpressionSyntax
lambdaExpression
,
I
MethodSymbol
delegateInvokeMethod
,
CancellationToken
cancellationToken
)
{
int
i
=
0
;
return
lambdaExpression
.
ParameterList
.
ReplaceNodes
(
...
...
@@ -211,7 +205,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
var
parameter
=
semanticModel
.
GetDeclaredSymbol
(
parameterNode
,
cancellationToken
);
parameterNode
=
parameterNode
.
WithType
(
parameter
?.
Type
.
GenerateTypeSyntax
()
??
s_objectType
);
var
param
=
namedTypeSymbol
.
D
elegateInvokeMethod
.
Parameters
[
i
++];
var
param
=
d
elegateInvokeMethod
.
Parameters
[
i
++];
if
(
param
.
HasExplicitDefaultValue
)
{
parameterNode
=
parameterNode
.
WithDefault
(
GetDefaultValue
(
param
));
...
...
@@ -222,9 +216,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
}
private
static
EqualsValueClauseSyntax
GetDefaultValue
(
IParameterSymbol
parameter
)
{
return
SyntaxFactory
.
EqualsValueClause
(
ExpressionGenerator
.
GenerateExpression
(
parameter
.
Type
,
parameter
.
ExplicitDefaultValue
,
canUseFieldReference
:
true
));
}
=>
SyntaxFactory
.
EqualsValueClause
(
ExpressionGenerator
.
GenerateExpression
(
parameter
.
Type
,
parameter
.
ExplicitDefaultValue
,
canUseFieldReference
:
true
));
private
class
MyCodeAction
:
CodeAction
.
DocumentChangeAction
{
...
...
src/Features/CSharp/Portable/UseLocalFunction/CSharpUseLocalFunctionDiagnosticAnalyzer.cs
浏览文件 @
adf8298e
...
...
@@ -10,6 +10,7 @@
using
Microsoft.CodeAnalysis.CSharp.Extensions
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.Diagnostics
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
namespace
Microsoft.CodeAnalysis.CSharp.UseLocalFunction
...
...
@@ -117,7 +118,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTyp
return
;
}
if
(!
CanReplaceAnonymousWithLocalFunction
(
semanticModel
,
expressionTypeOpt
,
local
,
block
,
anonymousFunction
,
out
var
l
ocations
,
cancellationToken
))
if
(!
CanReplaceAnonymousWithLocalFunction
(
semanticModel
,
expressionTypeOpt
,
local
,
block
,
anonymousFunction
,
out
var
explicitInvokeCallL
ocations
,
cancellationToken
))
{
return
;
}
...
...
@@ -127,10 +128,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTyp
localDeclaration
.
GetLocation
(),
anonymousFunction
.
GetLocation
());
if
(!
locations
.
IsEmpty
)
{
additionalLocations
=
additionalLocations
.
AddRange
(
locations
);
}
additionalLocations
=
additionalLocations
.
AddRange
(
explicitInvokeCallLocations
);
if
(
severity
!=
DiagnosticSeverity
.
Hidden
)
{
...
...
@@ -203,12 +201,12 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTyp
private
bool
CanReplaceAnonymousWithLocalFunction
(
SemanticModel
semanticModel
,
INamedTypeSymbol
expressionTypeOpt
,
ISymbol
local
,
BlockSyntax
block
,
AnonymousFunctionExpressionSyntax
anonymousFunction
,
out
ImmutableArray
<
Location
>
l
ocations
,
CancellationToken
cancellationToken
)
AnonymousFunctionExpressionSyntax
anonymousFunction
,
out
ImmutableArray
<
Location
>
explicitInvokeCallL
ocations
,
CancellationToken
cancellationToken
)
{
// Check all the references to the anonymous function and disallow the conversion if
// they're used in certain ways.
List
<
Location
>
delegateInvokeMethodLocations
=
null
;
l
ocations
=
ImmutableArray
<
Location
>.
Empty
;
var
explicitInvokeCalls
=
ArrayBuilder
<
Location
>.
GetInstance
()
;
explicitInvokeCallL
ocations
=
ImmutableArray
<
Location
>.
Empty
;
var
anonymousFunctionStart
=
anonymousFunction
.
SpanStart
;
foreach
(
var
descendentNode
in
block
.
DescendantNodes
())
{
...
...
@@ -250,8 +248,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTyp
}
else
{
delegateInvokeMethodLocations
=
delegateInvokeMethodLocations
??
new
List
<
Location
>();
delegateInvokeMethodLocations
.
Add
(
memberAccessExpression
.
GetLocation
());
explicitInvokeCalls
.
Add
(
memberAccessExpression
.
GetLocation
());
}
}
...
...
@@ -274,7 +271,7 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext, INamedTyp
}
}
locations
=
delegateInvokeMethodLocations
.
AsImmutableOrEmpty
();
explicitInvokeCallLocations
=
explicitInvokeCalls
.
ToImmutableAndFree
();
return
true
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录