Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
6dfd11ef
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,发现更多精彩内容 >>
提交
6dfd11ef
编写于
10月 05, 2017
作者:
M
Martin Strecker
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Added support for type parameter and added support for more compiler diagnostics cases.
上级
3d943fe2
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
588 addition
and
76 deletion
+588
-76
src/EditorFeatures/CSharpTest/AddParameter/AddParameterTests.cs
...itorFeatures/CSharpTest/AddParameter/AddParameterTests.cs
+378
-23
src/Features/CSharp/Portable/AddParameter/CSharpAddParameterCodeFixProvider.cs
...ortable/AddParameter/CSharpAddParameterCodeFixProvider.cs
+9
-4
src/Features/CSharp/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.cs
...GenerateConstructor/GenerateConstructorCodeFixProvider.cs
+4
-0
src/Features/Core/Portable/AddParameter/AbstractAddParameterCodeFixProvider.cs
...table/AddParameter/AbstractAddParameterCodeFixProvider.cs
+152
-41
src/Features/VisualBasic/Portable/AddParameter/VisualBasicAddParameterCodeFixProvider.vb
...le/AddParameter/VisualBasicAddParameterCodeFixProvider.vb
+6
-1
src/Features/VisualBasic/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.vb
...GenerateConstructor/GenerateConstructorCodeFixProvider.vb
+1
-0
src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs
...arp/Portable/LanguageServices/CSharpSyntaxFactsService.cs
+26
-7
src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs
...anguageServices/SyntaxFactsService/ISyntaxFactsService.cs
+2
-0
src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb
...ortable/LanguageServices/VisualBasicSyntaxFactsService.vb
+10
-0
未找到文件。
src/EditorFeatures/CSharpTest/AddParameter/AddParameterTests.cs
浏览文件 @
6dfd11ef
...
...
@@ -758,8 +758,9 @@ void M2()
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
public
async
Task
TestInvocationExtensionMethod
()
{
await
TestAsync
(
var
code
=
@"
namespace N {
static class Extensions
{
public static void ExtensionM1(this object o)
...
...
@@ -772,8 +773,10 @@ void M1()
{
new object().[|ExtensionM1|](1);
}
}"
,
}}"
;
var
fix
=
@"
namespace N {
static class Extensions
{
public static void ExtensionM1(this object o, int v)
...
...
@@ -786,7 +789,8 @@ void M1()
{
new object().ExtensionM1(1);
}
}"
,
null
);
}}"
;
await
TestInRegularAndScriptAsync
(
code
,
fix
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
...
...
@@ -1007,12 +1011,20 @@ void M2()
M1(1, 2);
}
}"
;
using
(
var
workspace
=
CreateWorkspaceFromOptions
(
code
,
default
))
{
var
actions
=
await
GetCodeActionsAsync
(
workspace
,
default
);
Assert
.
True
(
actions
.
Length
==
1
);
}
var
fix1
=
@"
class C1
{
void M1(string s1, string s2) { }
void M1(int v, string s) { }
void M1(int i) { }
void M2()
{
M1(1, 2);
}
}"
;
await
TestInRegularAndScriptAsync
(
code
,
fix0
,
0
);
await
TestInRegularAndScriptAsync
(
code
,
fix1
,
1
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
...
...
@@ -1114,7 +1126,6 @@ void M2()
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
[
Trait
(
"TODO"
,
"Fix broken"
)]
public
async
Task
TestInvocationCS0305
()
{
var
code
=
...
...
@@ -1131,19 +1142,17 @@ void M2()
@"
class C1
{
void M1<T
>(T i, bool
v) { }
void M1<T
, T1>(T i, T1
v) { }
void M2()
{
M1<int, bool>(1, true);
}
}"
;
// Should be void M1<T, T1>(T i, T1 v) { }
await
TestInRegularAndScriptAsync
(
code
,
fix0
,
0
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
[
Trait
(
"TODO"
,
"Fix broken"
)]
public
async
Task
TestInvocationCS0308
()
{
var
code
=
...
...
@@ -1160,13 +1169,12 @@ void M2()
@"
class C1
{
void M1
(int i, bool
v) { }
void M1
<T>(int i, T
v) { }
void M2()
{
M1<bool>(1, true);
}
}"
;
// Should be void M1<T>(int i, T v) { }
await
TestInRegularAndScriptAsync
(
code
,
fix0
,
0
);
}
...
...
@@ -1192,7 +1200,6 @@ class C1 : I1
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
[
Trait
(
"TODO"
,
"Fix missing"
)]
public
async
Task
TestInvocationCS1503
()
{
var
code
=
...
...
@@ -1207,13 +1214,23 @@ void M2()
}
}
"
;
//Should fix second overload to void M1(double d, int v) { }
await
TestMissingAsync
(
code
);
var
fix0
=
@"
class C1
{
void M1(int i1, int i2) { }
void M1(double d, int v) { }
void M2()
{
M1(1.0, 1);
}
}
"
;
await
TestInRegularAndScriptAsync
(
code
,
fix0
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
[
Trait
(
"TODO"
,
"Fix missing"
)]
public
async
Task
TestInvocationCS1660
()
{
var
code
=
...
...
@@ -1228,13 +1245,23 @@ void M2()
}
}
"
;
//Should fix second overload to void M1(System.Action a, int v) { }
await
TestMissingAsync
(
code
);
var
fix
=
@"
class C1
{
void M1(int i1, int i2) { }
void M1(System.Action a, int v) { }
void M2()
{
M1(()=> { }, 1);
}
}
"
;
await
TestInRegularAndScriptAsync
(
code
,
fix
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
[
Trait
(
"TODO"
,
"Fix missing"
)]
public
async
Task
TestInvocationCS1739
()
{
var
code
=
...
...
@@ -1248,9 +1275,337 @@ void M2()
}
}
"
;
// Should fix to: void M1(int i1, int i2) { }
await
TestMissingAsync
(
code
);
var
fix
=
@"
class C1
{
void M1(int i1, int i2) { }
void M2()
{
M1(i2: 1);
}
}
"
;
await
TestInRegularAndScriptAsync
(
code
,
fix
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
public
async
Task
TestInvocationAddTypeParameter_AddTypeParameterIfUserSpecifiesOne_OnlyTypeArgument
()
{
var
code
=
@"
class C1
{
void M1() { }
void M2()
{
[|M1|]<bool>();
}
}
"
;
var
fix0
=
@"
class C1
{
void M1<T>() { }
void M2()
{
M1<bool>();
}
}
"
;
await
TestInRegularAndScriptAsync
(
code
,
fix0
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
public
async
Task
TestInvocationAddTypeParameter_AddTypeParameterIfUserSpecifiesOne_TypeArgumentAndParameterArgument
()
{
var
code
=
@"
class C1
{
void M1() { }
void M2()
{
[|M1|]<bool>(true);
}
}
"
;
var
fix0
=
@"
class C1
{
void M1<T>(T v) { }
void M2()
{
M1<bool>(true);
}
}
"
;
await
TestInRegularAndScriptAsync
(
code
,
fix0
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
public
async
Task
TestInvocation_ExisitingTypeArgumentIsNotGeneralized
()
{
var
code
=
@"
class C1
{
void M1<T>(T v) { }
void M2()
{
[|M1|](true, true);
}
}
"
;
var
fix0
=
@"
class C1
{
void M1<T>(T v, bool v1) { }
void M2()
{
M1(true, true);
}
}
"
;
await
TestInRegularAndScriptAsync
(
code
,
fix0
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
[
Trait
(
"TODO"
,
"Fix all partial definitions"
)]
public
async
Task
TestInvocationPartialClasses
()
{
var
code
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
namespace N1
{
partial class C1
{
partial void PartialM();
}
}
</Document>
<Document>
namespace N1
{
partial class C1
{
partial void PartialM() { }
void M1()
{
[|PartialM|](1);
}
}
}
</Document>
</Project>
</Workspace>"
;
var
fix0
=
@"
<Workspace>
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
<Document>
namespace N1
{
partial class C1
{
partial void PartialM(int v);
}
}
</Document>
<Document>
namespace N1
{
partial class C1
{
partial void PartialM() { }
void M1()
{
PartialM(1);
}
}
}
</Document>
</Project>
</Workspace>"
;
await
TestInRegularAndScriptAsync
(
code
,
fix0
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
[
Trait
(
"TODO"
,
"Code formatting"
)]
public
async
Task
TestObjectCreationAddTypeParameter_AddTypeParameterIfUserSpecifiesOne_TypeParameterAndParameterArgument
()
{
var
code
=
@"
class C1
{
C1() { }
void M2()
{
var c = new [|C1<bool>|](true);
}
}
"
;
var
fix0
=
@"
class C1<T>
{
C1(T v) { }
void M2()
{
var c = new C1<bool>(true);
}
}
"
;
await
TestInRegularAndScriptAsync
(
code
,
fix0
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
public
async
Task
TestObjectCreationAddTypeParameter_GeneralizeGenericArgument1
()
{
var
code
=
@"
class C1<T>
{
C1() { }
void M2()
{
var c = new [|C1<bool>|](true);
}
}
"
;
var
fix0
=
@"
class C1<T>
{
C1(T v) { }
void M2()
{
var c = new C1<bool>(true);
}
}
"
;
await
TestInRegularAndScriptAsync
(
code
,
fix0
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
public
async
Task
TestObjectCreationAddTypeParameter_GeneralizeGenericArgument2
()
{
var
code
=
@"
class C1<T>
{
C1() { }
void M1<U>() { }
void M2()
{
var c = new C1<bool>();
c.[|M1<int, bool>|]();
}
}
"
;
var
fix0
=
@"
class C1<T>
{
C1() { }
void M1<U, T1>() { }
void M2()
{
var c = new C1<bool>();
c.M1<int, bool>();
}
}
"
;
await
TestInRegularAndScriptAsync
(
code
,
fix0
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
public
async
Task
TestObjectCreationAddTypeParameter_GeneralizeGenericArgument3
()
{
var
code
=
@"
class C1<T>
{
C1() { }
void M1<U>() { }
void M2()
{
var c = new C1<bool>();
c.[|M1<int, string>|]();
}
}
"
;
var
fix0
=
@"
class C1<T>
{
C1() { }
void M1<U, T1>() { }
void M2()
{
var c = new C1<bool>();
c.M1<int, string>();
}
}
"
;
await
TestInRegularAndScriptAsync
(
code
,
fix0
);
}
[
WorkItem
(
21446
,
"https://github.com/dotnet/roslyn/issues/21446"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsAddParameter
)]
public
async
Task
TestObjectCreationAddTypeParameter_GeneralizeGenericArgument4
()
{
var
code
=
@"
class C1<T> where T: struct
{
C1() { }
void M1<U>() where U : struct
{
}
void M2()
{
var c = new C1<bool>();
c.[|M1<int, string>|]();
}
}
"
;
var
fix0
=
@"
class C1<T> where T: struct
{
C1() { }
void M1<U, T1>() where U : struct
{
}
void M2()
{
var c = new C1<bool>();
c.M1<int, string>();
}
}
"
;
await
TestInRegularAndScriptAsync
(
code
,
fix0
);
}
}
}
src/Features/CSharp/Portable/AddParameter/CSharpAddParameterCodeFixProvider.cs
浏览文件 @
6dfd11ef
...
...
@@ -20,7 +20,8 @@ internal class CSharpAddParameterCodeFixProvider : AbstractAddParameterCodeFixPr
ArgumentListSyntax
,
AttributeArgumentListSyntax
,
InvocationExpressionSyntax
,
ObjectCreationExpressionSyntax
>
ObjectCreationExpressionSyntax
,
TypeSyntax
>
{
private
static
readonly
ImmutableArray
<
string
>
AddParameterFixableDiagnosticIds
=
GenerateConstructorDiagnosticIds
.
AllDiagnosticIds
.
Union
(
...
...
@@ -28,9 +29,13 @@ internal class CSharpAddParameterCodeFixProvider : AbstractAddParameterCodeFixPr
Enumerable
.
Repeat
(
"CS1593"
,
1
)).
// C# Delegate 'Action' does not take 1 arguments
ToImmutableArray
();
public
override
ImmutableArray
<
string
>
FixableDiagnosticIds
=>
AddParameterFixableDiagnosticIds
;
public
override
ImmutableArray
<
string
>
FixableDiagnosticIds
=>
AddParameterFixableDiagnosticIds
;
protected
override
ImmutableArray
<
string
>
TooManyArgumentsDiagnosticIds
{
get
;
}
=
GenerateConstructorDiagnosticIds
.
TooManyArgumentsDiagnosticIds
;
protected
override
ImmutableArray
<
string
>
TooManyArgumentsDiagnosticIds
=>
GenerateConstructorDiagnosticIds
.
TooManyArgumentsDiagnosticIds
;
protected
override
ImmutableArray
<
string
>
CannotConvertDiagnosticIds
=>
GenerateConstructorDiagnosticIds
.
CannotConvertDiagnosticIds
;
}
}
src/Features/CSharp/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.cs
浏览文件 @
6dfd11ef
...
...
@@ -20,6 +20,7 @@ internal static class GenerateConstructorDiagnosticIds
public
const
string
CS1729
=
nameof
(
CS1729
);
// CS1729: 'C' does not contain a constructor that takes n arguments
public
const
string
CS1739
=
nameof
(
CS1739
);
// CS1739: The best overload for 'Program' does not have a parameter named 'v'
public
const
string
CS1503
=
nameof
(
CS1503
);
// CS1503: Argument 1: cannot convert from 'T1' to 'T2'
public
const
string
CS1660
=
nameof
(
CS1660
);
// CS1660: Cannot convert lambda expression to type 'string[]' because it is not a delegate type
public
const
string
CS7036
=
nameof
(
CS7036
);
// CS7036: There is no argument given that corresponds to the required formal parameter 'v' of 'C.C(int)'
public
static
readonly
ImmutableArray
<
string
>
AllDiagnosticIds
=
...
...
@@ -27,6 +28,9 @@ internal static class GenerateConstructorDiagnosticIds
public
static
readonly
ImmutableArray
<
string
>
TooManyArgumentsDiagnosticIds
=
ImmutableArray
.
Create
(
CS1729
);
public
static
readonly
ImmutableArray
<
string
>
CannotConvertDiagnosticIds
=
ImmutableArray
.
Create
(
CS1503
,
CS1660
);
}
/// <summary>
...
...
src/Features/Core/Portable/AddParameter/AbstractAddParameterCodeFixProvider.cs
浏览文件 @
6dfd11ef
...
...
@@ -25,14 +25,17 @@ internal abstract class AbstractAddParameterCodeFixProvider<
TArgumentListSyntax
,
TAttributeArgumentListSyntax
,
TInvocationExpressionSyntax
,
TObjectCreationExpressionSyntax
>
:
CodeFixProvider
TObjectCreationExpressionSyntax
,
TTypeSyntax
>
:
CodeFixProvider
where
TArgumentSyntax
:
SyntaxNode
where
TArgumentListSyntax
:
SyntaxNode
where
TAttributeArgumentListSyntax
:
SyntaxNode
where
TInvocationExpressionSyntax
:
SyntaxNode
where
TObjectCreationExpressionSyntax
:
SyntaxNode
where
TTypeSyntax
:
SyntaxNode
{
protected
abstract
ImmutableArray
<
string
>
TooManyArgumentsDiagnosticIds
{
get
;
}
protected
abstract
ImmutableArray
<
string
>
CannotConvertDiagnosticIds
{
get
;
}
public
override
async
Task
RegisterCodeFixesAsync
(
CodeFixContext
context
)
{
...
...
@@ -69,6 +72,11 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
return
null
;
}
if
(
this
.
CannotConvertDiagnosticIds
.
Contains
(
diagnostic
.
Id
))
{
return
null
;
}
return
initialNode
.
GetAncestorsOrThis
<
TArgumentSyntax
>()
.
LastOrDefault
(
a
=>
a
.
AncestorsAndSelf
().
Contains
(
node
));
}
...
...
@@ -89,6 +97,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
var
symbolInfo
=
semanticModel
.
GetSymbolInfo
(
expression
,
cancellationToken
);
var
candidates
=
symbolInfo
.
CandidateSymbols
.
OfType
<
IMethodSymbol
>().
ToImmutableArray
();
if
(
candidates
.
Length
==
0
)
{
// Invocation might be on an delegate. We try to find the declaration of the delegate.
...
...
@@ -108,7 +117,9 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
}
var
arguments
=
(
SeparatedSyntaxList
<
TArgumentSyntax
>)
syntaxFacts
.
GetArgumentsOfInvocationExpression
(
invocationExpression
);
var
argumentInsertPositionInMethodCandidates
=
GetArgumentInsertPositionForMethodCandidates
(
argumentOpt
,
semanticModel
,
syntaxFacts
,
arguments
,
candidates
);
var
typeArguments
=
(
SeparatedSyntaxList
<
TTypeSyntax
>)
syntaxFacts
.
GetTypeArgumentsOfInvocationExpression
(
invocationExpression
);
var
argumentInsertPositionInMethodCandidates
=
GetArgumentInsertPositionAndTypeArgumentForMethodCandidates
(
semanticModel
,
syntaxFacts
,
candidates
,
arguments
,
argumentOpt
,
typeArguments
);
RegisterFixForMethodOverloads
(
context
,
arguments
,
argumentInsertPositionInMethodCandidates
);
}
...
...
@@ -144,18 +155,17 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
var
arguments
=
(
SeparatedSyntaxList
<
TArgumentSyntax
>)
syntaxFacts
.
GetArgumentsOfObjectCreationExpression
(
objectCreation
);
var
methodCandidates
=
type
.
InstanceConstructors
;
var
constructorsAndArgumentToAdd
=
GetArgumentInsertPositionForMethodCandidates
(
argumentOpt
,
semanticModel
,
syntaxFacts
,
arguments
,
methodCandidates
);
RegisterFixForMethodOverloads
(
context
,
arguments
,
constructorsAndArgumentToAdd
);
var
typeArguments
=
(
SeparatedSyntaxList
<
TTypeSyntax
>)
syntaxFacts
.
GetTypeArgumentsOfObjectCreationExpression
(
objectCreation
);
var
candidates
=
GetArgumentInsertPositionAndTypeArgumentForMethodCandidates
(
semanticModel
,
syntaxFacts
,
methodCandidates
,
arguments
,
argumentOpt
,
typeArguments
);
RegisterFixForMethodOverloads
(
context
,
arguments
,
candidates
);
}
private
void
RegisterFixForMethodOverloads
(
CodeFixContext
context
,
SeparatedSyntaxList
<
TArgumentSyntax
>
arguments
,
ImmutableArray
<(
IMethodSymbol
method
,
TArgumentSyntax
argument
,
int
index
)>
methodsAndArgumentToAdd
)
private
void
RegisterFixForMethodOverloads
(
CodeFixContext
context
,
SeparatedSyntaxList
<
TArgumentSyntax
>
arguments
,
ImmutableArray
<(
IMethodSymbol
method
,
TArgumentSyntax
argument
,
int
index
,
TTypeSyntax
typeArgument
)>
methodsAndArgumentToAdd
)
{
// Order by the furthest argument index to the nearest argument index. The ones with
// larger argument indexes mean that we matched more earlier arguments (and thus are
// likely to be the correct match).
foreach
(
var
(
method
,
argumentToAdd
,
_
)
in
methodsAndArgumentToAdd
.
OrderByDescending
(
t
=>
t
.
index
))
foreach
(
var
(
method
,
argumentToAdd
,
_
,
typeArgument
)
in
methodsAndArgumentToAdd
.
OrderByDescending
(
t
=>
t
.
index
))
{
var
parameters
=
method
.
Parameters
.
Select
(
p
=>
p
.
ToDisplayString
(
SimpleFormat
));
var
signature
=
$"
{
method
.
Name
}
(
{
string
.
Join
(
", "
,
parameters
)}
)"
;
...
...
@@ -163,38 +173,32 @@ private void RegisterFixForMethodOverloads(CodeFixContext context, SeparatedSynt
var
title
=
string
.
Format
(
FeaturesResources
.
Add_parameter_to_0
,
signature
);
context
.
RegisterCodeFix
(
new
MyCodeAction
(
title
,
c
=>
FixAsync
(
context
.
Document
,
method
,
argumentToAdd
,
arguments
,
c
)),
new
MyCodeAction
(
title
,
c
=>
FixAsync
(
context
.
Document
,
method
,
argumentToAdd
,
arguments
,
typeArgument
,
c
)),
context
.
Diagnostics
);
}
}
private
ImmutableArray
<(
IMethodSymbol
method
,
TArgumentSyntax
argument
,
int
index
)>
GetArgumentInsertPositionForMethodCandidates
(
TArgumentSyntax
argumentOpt
,
SemanticModel
semanticModel
,
ISyntaxFactsService
syntaxFacts
,
SeparatedSyntaxList
<
TArgumentSyntax
>
arguments
,
ImmutableArray
<
IMethodSymbol
>
methodCandidates
)
private
ImmutableArray
<(
IMethodSymbol
method
,
TArgumentSyntax
argument
,
int
index
,
TTypeSyntax
typeArgument
)>
GetArgumentInsertPositionAndTypeArgumentForMethodCandidates
(
SemanticModel
semanticModel
,
ISyntaxFactsService
syntaxFacts
,
ImmutableArray
<
IMethodSymbol
>
methodCandidates
,
SeparatedSyntaxList
<
TArgumentSyntax
>
arguments
,
TArgumentSyntax
argumentOpt
,
SeparatedSyntaxList
<
TTypeSyntax
>
typeArguments
)
{
var
comparer
=
syntaxFacts
.
StringComparer
;
var
methodsAndArgumentToAdd
=
ArrayBuilder
<(
IMethodSymbol
constructor
,
TArgumentSyntax
argument
,
int
index
)>.
GetInstance
();
var
methodsAndArgumentToAdd
=
ArrayBuilder
<(
IMethodSymbol
constructor
,
TArgumentSyntax
argument
,
int
index
,
TTypeSyntax
typeArgument
)>.
GetInstance
();
foreach
(
var
method
in
methodCandidates
.
OrderBy
(
m
=>
m
.
Parameters
.
Length
))
{
if
(
method
.
IsNonImplicitAndFromSource
()
&&
NonParamsParameterCount
(
method
)
<
arguments
.
Count
)
if
(
method
.
IsNonImplicitAndFromSource
())
{
var
argumentToAdd
=
DetermineFirstArgumentToAdd
(
semanticModel
,
syntaxFacts
,
comparer
,
method
,
arguments
,
argumentOpt
);
var
argumentToAdd
=
GetArgumentInsertPositionForMethodCandidate
(
semanticModel
,
syntaxFacts
,
method
,
arguments
,
argumentOpt
);
var
typeArgumentToAdd
=
GetTypeArgumentForMethodCandidate
(
method
,
typeArguments
);
if
(
argumentToAdd
!=
null
)
if
(
argumentToAdd
!=
null
||
typeArgumentToAdd
!=
null
)
{
if
(
argumentOpt
!=
null
&&
argumentToAdd
!=
argumentOpt
)
{
// We were trying to fix a specific argument, but the argument we want
// to fix is something different. That means there was an error earlier
// than this argument. Which means we're looking at a non-viable
// constructor. Skip this one.
continue
;
}
methodsAndArgumentToAdd
.
Add
(
(
method
,
argumentToAdd
,
arguments
.
IndexOf
(
argumentToAdd
)));
(
method
,
argumentToAdd
,
arguments
.
IndexOf
(
argumentToAdd
)
,
typeArgumentToAdd
));
}
}
}
...
...
@@ -202,6 +206,49 @@ private ImmutableArray<(IMethodSymbol method, TArgumentSyntax argument, int inde
return
methodsAndArgumentToAdd
.
ToImmutableArray
();
}
private
TTypeSyntax
GetTypeArgumentForMethodCandidate
(
IMethodSymbol
method
,
SeparatedSyntaxList
<
TTypeSyntax
>
typeArguments
)
{
var
typeParameter
=
method
.
IsConstructor
()
?
method
.
ContainingType
.
TypeParameters
:
method
.
TypeParameters
;
if
(
typeArguments
.
Count
>
typeParameter
.
Length
)
{
return
typeArguments
[
typeParameter
.
Length
];
}
return
null
;
}
private
TArgumentSyntax
GetArgumentInsertPositionForMethodCandidate
(
SemanticModel
semanticModel
,
ISyntaxFactsService
syntaxFacts
,
IMethodSymbol
method
,
SeparatedSyntaxList
<
TArgumentSyntax
>
arguments
,
TArgumentSyntax
argumentOpt
)
{
var
comparer
=
syntaxFacts
.
StringComparer
;
var
isNamedArgument
=
!
string
.
IsNullOrWhiteSpace
(
syntaxFacts
.
GetNameForArgument
(
argumentOpt
));
if
(
isNamedArgument
||
NonParamsParameterCount
(
method
)
<
arguments
.
Count
)
{
var
argumentToAdd
=
DetermineFirstArgumentToAdd
(
semanticModel
,
syntaxFacts
,
comparer
,
method
,
arguments
,
argumentOpt
);
if
(
argumentToAdd
!=
null
)
{
if
(
argumentOpt
!=
null
&&
argumentToAdd
!=
argumentOpt
)
{
// We were trying to fix a specific argument, but the argument we want
// to fix is something different. That means there was an error earlier
// than this argument. Which means we're looking at a non-viable
// constructor. Skip this one.
return
null
;
}
}
return
argumentToAdd
;
}
return
null
;
}
private
int
NonParamsParameterCount
(
IMethodSymbol
method
)
=>
method
.
IsParams
()
?
method
.
Parameters
.
Length
-
1
:
method
.
Parameters
.
Length
;
...
...
@@ -210,17 +257,46 @@ private int NonParamsParameterCount(IMethodSymbol method)
IMethodSymbol
method
,
TArgumentSyntax
argument
,
SeparatedSyntaxList
<
TArgumentSyntax
>
argumentList
,
TTypeSyntax
newTypeArgument
,
CancellationToken
cancellationToken
)
{
var
methodDeclaration
=
await
method
.
DeclaringSyntaxReferences
[
0
].
GetSyntaxAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
(
parameterSymbol
,
isNamedArgument
)
=
await
CreateParameterSymbolAsync
(
invocationDocument
,
method
,
argument
,
cancellationToken
).
ConfigureAwait
(
false
);
var
methodDeclarationRoot
=
methodDeclaration
.
SyntaxTree
.
GetRoot
(
cancellationToken
);
var
methodDocument
=
invocationDocument
.
Project
.
Solution
.
GetDocument
(
methodDeclaration
.
SyntaxTree
);
var
syntaxFacts
=
methodDocument
.
GetLanguageService
<
ISyntaxFactsService
>();
var
methodDeclarationRoot
=
methodDeclaration
.
SyntaxTree
.
GetRoot
(
cancellationToken
);
var
editor
=
new
SyntaxEditor
(
methodDeclarationRoot
,
methodDocument
.
Project
.
Solution
.
Workspace
);
var
parameterDeclaration
=
default
(
SyntaxNode
);
var
insertionIndex
=
default
(
int
);
var
newTypeParameter
=
newTypeArgument
==
null
?
null
:
CreateTypeParameterSymbol
(
method
);
if
(
argument
!=
null
)
{
(
parameterDeclaration
,
insertionIndex
)
=
await
CreateParameterDeclarationAsync
(
editor
,
invocationDocument
,
method
,
methodDeclaration
,
argumentList
,
argument
,
newTypeArgument
,
newTypeParameter
,
cancellationToken
).
ConfigureAwait
(
false
);
}
AddParameter
(
syntaxFacts
,
editor
,
method
,
methodDeclaration
,
argument
,
insertionIndex
,
parameterDeclaration
,
newTypeParameter
,
cancellationToken
);
var
newRoot
=
editor
.
GetChangedRoot
();
var
newDocument
=
methodDocument
.
WithSyntaxRoot
(
newRoot
);
return
newDocument
;
}
private
async
Task
<(
SyntaxNode
parameterDeclaration
,
int
insertionIndex
)>
CreateParameterDeclarationAsync
(
SyntaxEditor
editor
,
Document
invocationDocument
,
IMethodSymbol
method
,
SyntaxNode
methodDeclaration
,
SeparatedSyntaxList
<
TArgumentSyntax
>
argumentList
,
TArgumentSyntax
argument
,
TTypeSyntax
newTypeArgument
,
ITypeParameterSymbol
newTypeParameter
,
CancellationToken
cancellationToken
)
{
var
(
parameterSymbol
,
isNamedArgument
)
=
await
CreateParameterSymbolAsync
(
invocationDocument
,
method
,
argument
,
newTypeArgument
,
newTypeParameter
,
cancellationToken
).
ConfigureAwait
(
false
);
var
parameterDeclaration
=
editor
.
Generator
.
ParameterDeclaration
(
parameterSymbol
)
.
WithAdditionalAnnotations
(
Formatter
.
Annotation
);
...
...
@@ -235,30 +311,54 @@ private int NonParamsParameterCount(IMethodSymbol method)
insertionIndex
++;
}
AddParameter
(
syntaxFacts
,
editor
,
methodDeclaration
,
argument
,
insertionIndex
,
parameterDeclaration
,
cancellationToken
);
var
newRoot
=
editor
.
GetChangedRoot
();
var
newDocument
=
methodDocument
.
WithSyntaxRoot
(
newRoot
);
return
(
parameterDeclaration
,
insertionIndex
);
}
return
newDocument
;
private
static
ITypeParameterSymbol
CreateTypeParameterSymbol
(
IMethodSymbol
method
)
{
var
exisitingTypeParameter
=
method
.
GetAllTypeParameters
();
var
typeParameterName
=
NameGenerator
.
GenerateUniqueName
(
"T"
,
n
=>
exisitingTypeParameter
.
All
(
symbol
=>
symbol
.
Name
!=
n
));
return
CodeGenerationSymbolFactory
.
CreateTypeParameterSymbol
(
typeParameterName
);
}
private
static
ImmutableArray
<
ITypeParameterSymbol
>
GetTypeParameterOfClassOrMethod
(
IMethodSymbol
method
)
=>
method
.
IsConstructor
()
?
(
method
.
ContainingSymbol
as
ITypeSymbol
).
GetAllTypeParameters
()
:
method
.
TypeParameters
;
private
async
Task
<(
IParameterSymbol
,
bool
isNamedArgument
)>
CreateParameterSymbolAsync
(
Document
invocationDocument
,
IMethodSymbol
method
,
TArgumentSyntax
argument
,
TTypeSyntax
newTypeArgument
,
ITypeParameterSymbol
newTypeParameter
,
CancellationToken
cancellationToken
)
{
var
syntaxFacts
=
invocationDocument
.
GetLanguageService
<
ISyntaxFactsService
>();
var
semanticFacts
=
invocationDocument
.
GetLanguageService
<
ISemanticFactsService
>();
var
argumentName
=
syntaxFacts
.
GetNameForArgument
(
argument
);
var
expression
=
syntaxFacts
.
GetExpressionOfArgument
(
argument
);
var
semanticModel
=
await
invocationDocument
.
GetSemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
parameterType
=
semanticModel
.
GetTypeInfo
(
expression
).
Type
??
semanticModel
.
Compilation
.
ObjectType
;
if
(
newTypeArgument
!=
null
)
{
var
typeArgumentType
=
semanticModel
.
GetTypeInfo
(
newTypeArgument
).
Type
;
if
(
typeArgumentType
==
parameterType
)
{
parameterType
=
newTypeParameter
;
}
}
var
typeArguments
=
method
.
GetAllTypeArguments
();
var
fittingTypeArgumentIndex
=
typeArguments
.
IndexOf
(
parameterType
);
if
(
fittingTypeArgumentIndex
>=
0
)
{
var
typeParameter
=
method
.
GetAllTypeParameters
();
parameterType
=
typeParameter
[
fittingTypeArgumentIndex
];
}
if
(!
string
.
IsNullOrWhiteSpace
(
argumentName
))
{
var
newParameterSymbol
=
CodeGenerationSymbolFactory
.
CreateParameterSymbol
(
...
...
@@ -282,15 +382,26 @@ private int NonParamsParameterCount(IMethodSymbol method)
private
static
void
AddParameter
(
ISyntaxFactsService
syntaxFacts
,
SyntaxEditor
editor
,
IMethodSymbol
methodSymbol
,
SyntaxNode
declaration
,
TArgumentSyntax
argument
,
int
insertionIndex
,
SyntaxNode
parameterDeclaration
,
ITypeParameterSymbol
typeParameter
,
CancellationToken
cancellationToken
)
{
var
sourceText
=
declaration
.
SyntaxTree
.
GetText
(
cancellationToken
);
var
generator
=
editor
.
Generator
;
//Append the new type parameter to the end of the type parameter list
if
(
typeParameter
!=
null
)
{
var
typeParameters
=
GetTypeParameterOfClassOrMethod
(
methodSymbol
).
Add
(
typeParameter
);
var
typeDeclarationSyntax
=
syntaxFacts
.
GetContainingTypeDeclaration
(
declaration
,
declaration
.
SpanStart
);
var
typeParameterDeclaration
=
methodSymbol
.
IsConstructor
()
?
typeDeclarationSyntax
:
declaration
;
editor
.
SetTypeParameters
(
typeParameterDeclaration
,
typeParameters
.
Select
(
tp
=>
tp
.
Name
));
}
var
existingParameters
=
generator
.
GetParameters
(
declaration
);
var
placeOnNewLine
=
ShouldPlaceParametersOnNewLine
(
existingParameters
,
cancellationToken
);
...
...
src/Features/VisualBasic/Portable/AddParameter/VisualBasicAddParameterCodeFixProvider.vb
浏览文件 @
6dfd11ef
...
...
@@ -17,12 +17,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddParameter
ArgumentListSyntax
,
ArgumentListSyntax
,
InvocationExpressionSyntax
,
ObjectCreationExpressionSyntax
)
ObjectCreationExpressionSyntax
,
TypeSyntax
)
Public
Overrides
ReadOnly
Property
FixableDiagnosticIds
As
ImmutableArray
(
Of
String
)
=
GenerateConstructorDiagnosticIds
.
AllDiagnosticIds
Protected
Overrides
ReadOnly
Property
TooManyArgumentsDiagnosticIds
As
ImmutableArray
(
Of
String
)
=
GenerateConstructorDiagnosticIds
.
TooManyArgumentsDiagnosticIds
Protected
Overrides
ReadOnly
Property
CannotConvertDiagnosticIds
As
ImmutableArray
(
Of
String
)
=
GenerateConstructorDiagnosticIds
.
CannotConvertDiagnosticIds
End
Class
End
Namespace
src/Features/VisualBasic/Portable/GenerateConstructor/GenerateConstructorCodeFixProvider.vb
浏览文件 @
6dfd11ef
...
...
@@ -22,6 +22,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateConstructor
Friend
Shared
ReadOnly
AllDiagnosticIds
As
ImmutableArray
(
Of
String
)
=
ImmutableArray
.
Create
(
BC30057
,
BC30272
,
BC30274
,
BC30389
,
BC30455
,
BC32006
,
BC30512
,
BC30387
)
Friend
Shared
ReadOnly
TooManyArgumentsDiagnosticIds
As
ImmutableArray
(
Of
String
)
=
ImmutableArray
.
Create
(
BC30057
)
Friend
Shared
ReadOnly
CannotConvertDiagnosticIds
As
ImmutableArray
(
Of
String
)
=
ImmutableArray
.
Create
(
BC30512
,
BC32006
)
End
Class
<
ExportCodeFixProvider
(
LanguageNames
.
VisualBasic
,
Name
:
=
PredefinedCodeFixProviderNames
.
GenerateConstructor
),
[
Shared
]
>
...
...
src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs
浏览文件 @
6dfd11ef
...
...
@@ -42,7 +42,7 @@ public SyntaxTrivia ElasticCarriageReturnLineFeed
protected
override
IDocumentationCommentService
DocumentationCommentService
=>
CSharpDocumentationCommentService
.
Instance
;
public
bool
SupportsIndexingInitializer
(
ParseOptions
options
)
public
bool
SupportsIndexingInitializer
(
ParseOptions
options
)
=>
((
CSharpParseOptions
)
options
).
LanguageVersion
>=
LanguageVersion
.
CSharp6
;
public
bool
SupportsThrowExpression
(
ParseOptions
options
)
...
...
@@ -259,10 +259,10 @@ public bool IsReturnStatement(SyntaxNode node)
public
bool
IsStatement
(
SyntaxNode
node
)
=>
node
is
StatementSyntax
;
public
bool
IsParameter
(
SyntaxNode
node
)
=>
node
is
ParameterSyntax
;
public
bool
IsVariableDeclarator
(
SyntaxNode
node
)
=>
node
is
VariableDeclaratorSyntax
;
...
...
@@ -1343,6 +1343,25 @@ public SeparatedSyntaxList<SyntaxNode> GetArgumentsOfObjectCreationExpression(Sy
public
SeparatedSyntaxList
<
SyntaxNode
>
GetArgumentsOfArgumentList
(
SyntaxNode
argumentList
)
=>
(
argumentList
as
ArgumentListSyntax
)?.
Arguments
??
default
(
SeparatedSyntaxList
<
SyntaxNode
>);
public
SeparatedSyntaxList
<
SyntaxNode
>
GetTypeArgumentsOfInvocationExpression
(
SyntaxNode
invocationExpression
)
{
if
(
invocationExpression
is
InvocationExpressionSyntax
invocationExpressionSyntax
)
{
switch
(
invocationExpressionSyntax
.
Expression
)
{
case
GenericNameSyntax
genericName
:
return
genericName
.
TypeArgumentList
.
Arguments
;
case
MemberAccessExpressionSyntax
memberAccessExpression
when
memberAccessExpression
.
Name
is
GenericNameSyntax
genericName
:
return
genericName
.
TypeArgumentList
.
Arguments
;
}
}
return
default
(
SeparatedSyntaxList
<
SyntaxNode
>);
}
public
SeparatedSyntaxList
<
SyntaxNode
>
GetTypeArgumentsOfObjectCreationExpression
(
SyntaxNode
objectCreationExpression
)
=>
((
objectCreationExpression
as
ObjectCreationExpressionSyntax
)?.
Type
as
GenericNameSyntax
)?.
TypeArgumentList
?.
Arguments
??
default
(
SeparatedSyntaxList
<
SyntaxNode
>);
public
bool
IsRegularComment
(
SyntaxTrivia
trivia
)
=>
trivia
.
IsRegularComment
();
...
...
@@ -1422,7 +1441,7 @@ public bool IsDeclaration(SyntaxNode node)
private
static
readonly
SyntaxAnnotation
s_annotation
=
new
SyntaxAnnotation
();
public
void
AddFirstMissingCloseBrace
(
SyntaxNode
root
,
SyntaxNode
contextNode
,
SyntaxNode
root
,
SyntaxNode
contextNode
,
out
SyntaxNode
newRoot
,
out
SyntaxNode
newContextNode
)
{
// First, annotate the context node in the tree so that we can find it again
...
...
@@ -1587,9 +1606,9 @@ public override bool IsShebangDirectiveTrivia(SyntaxTrivia trivia)
public
override
bool
IsPreprocessorDirective
(
SyntaxTrivia
trivia
)
=>
SyntaxFacts
.
IsPreprocessorDirective
(
trivia
.
Kind
());
private
class
AddFirstMissingCloseBaceRewriter
:
CSharpSyntaxRewriter
private
class
AddFirstMissingCloseBaceRewriter
:
CSharpSyntaxRewriter
{
private
readonly
SyntaxNode
_contextNode
;
private
readonly
SyntaxNode
_contextNode
;
private
bool
_seenContextNode
=
false
;
private
bool
_addedFirstCloseCurly
=
false
;
...
...
@@ -1626,7 +1645,7 @@ public override SyntaxNode Visit(SyntaxNode node)
// then still ask to format its close curly to make sure all the
// curlies up the stack are properly formatted.
var
braces
=
rewritten
.
GetBraces
();
if
(
braces
.
openBrace
.
Kind
()
==
SyntaxKind
.
None
&&
if
(
braces
.
openBrace
.
Kind
()
==
SyntaxKind
.
None
&&
braces
.
closeBrace
.
Kind
()
==
SyntaxKind
.
None
)
{
// Not an item with braces. Just pass it up.
...
...
src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs
浏览文件 @
6dfd11ef
...
...
@@ -172,6 +172,8 @@ internal interface ISyntaxFactsService : ILanguageService
SeparatedSyntaxList
<
SyntaxNode
>
GetArgumentsOfInvocationExpression
(
SyntaxNode
node
);
SeparatedSyntaxList
<
SyntaxNode
>
GetArgumentsOfObjectCreationExpression
(
SyntaxNode
node
);
SeparatedSyntaxList
<
SyntaxNode
>
GetArgumentsOfArgumentList
(
SyntaxNode
node
);
SeparatedSyntaxList
<
SyntaxNode
>
GetTypeArgumentsOfInvocationExpression
(
SyntaxNode
node
);
SeparatedSyntaxList
<
SyntaxNode
>
GetTypeArgumentsOfObjectCreationExpression
(
SyntaxNode
node
);
bool
IsUsingDirectiveName
(
SyntaxNode
node
);
bool
IsIdentifierName
(
SyntaxNode
node
);
...
...
src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb
浏览文件 @
6dfd11ef
...
...
@@ -1273,6 +1273,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return
If
(
arguments
.
HasValue
,
arguments
.
Value
,
Nothing
)
End
Function
Public
Function
GetTypeArgumentsOfInvocationExpression
(
invocationExpression
As
SyntaxNode
)
As
SeparatedSyntaxList
(
Of
SyntaxNode
)
Implements
ISyntaxFactsService
.
GetTypeArgumentsOfInvocationExpression
Dim
arguments
=
TryCast
(
TryCast
(
invocationExpression
,
InvocationExpressionSyntax
)
?
.
Expression
,
GenericNameSyntax
)
?
.
TypeArgumentList
?
.
Arguments
Return
If
(
arguments
.
HasValue
,
arguments
.
Value
,
Nothing
)
End
Function
Public
Function
GetTypeArgumentsOfObjectCreationExpression
(
objectCreationExpression
As
SyntaxNode
)
As
SeparatedSyntaxList
(
Of
SyntaxNode
)
Implements
ISyntaxFactsService
.
GetTypeArgumentsOfObjectCreationExpression
Dim
arguments
=
TryCast
(
TryCast
(
objectCreationExpression
,
ObjectCreationExpressionSyntax
)
?
.
Type
,
GenericNameSyntax
)
?
.
TypeArgumentList
?
.
Arguments
Return
If
(
arguments
.
HasValue
,
arguments
.
Value
,
Nothing
)
End
Function
Public
Function
ConvertToSingleLine
(
node
As
SyntaxNode
,
Optional
useElasticTrivia
As
Boolean
=
False
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
ConvertToSingleLine
Return
node
.
ConvertToSingleLine
(
useElasticTrivia
)
End
Function
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录