Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
ffad2b58
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,发现更多精彩内容 >>
提交
ffad2b58
编写于
3月 22, 2020
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Working, with tests.
上级
eff5e315
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
255 addition
and
127 deletion
+255
-127
src/EditorFeatures/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs
...InitializeParameter/InitializeMemberFromParameterTests.cs
+121
-0
src/Features/CSharp/Portable/InitializeParameter/CSharpAddParameterCheckCodeRefactoringProvider.cs
...rameter/CSharpAddParameterCheckCodeRefactoringProvider.cs
+2
-2
src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromParameterCodeRefactoringProvider.cs
...rpInitializeMemberFromParameterCodeRefactoringProvider.cs
+3
-2
src/Features/CSharp/Portable/InitializeParameter/InitializeParameterHelpers.cs
...ortable/InitializeParameter/InitializeParameterHelpers.cs
+2
-2
src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs
...meter/AbstractAddParameterCheckCodeRefactoringProvider.cs
+1
-1
src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs
...mberFromParameterCodeRefactoringProviderMemberCreation.cs
+122
-117
src/Features/Core/Portable/InitializeParameter/AbstractInitializeParameterCodeRefactoringProvider.cs
...ter/AbstractInitializeParameterCodeRefactoringProvider.cs
+1
-1
src/Features/VisualBasic/Portable/InitializeParameter/VisualBasicAddParameterCheckCodeRefactoringProvider.vb
...er/VisualBasicAddParameterCheckCodeRefactoringProvider.vb
+1
-1
src/Features/VisualBasic/Portable/InitializeParameter/VisualBasicInitializeMemberFromParameterCodeRefactoringProvider.vb
...icInitializeMemberFromParameterCodeRefactoringProvider.vb
+2
-1
未找到文件。
src/EditorFeatures/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs
浏览文件 @
ffad2b58
...
...
@@ -1618,5 +1618,126 @@ public C(int i, string s)
}
}"
);
}
[
WorkItem
(
35665
,
"https://github.com/dotnet/roslyn/issues/35665"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsInitializeParameter
)]
public
async
Task
TestGenerateRemainingFields1
()
{
await
TestInRegularAndScript1Async
(
@"
class C
{
public C([||]int i, int j, int k)
{
}
}"
,
@"
class C
{
private readonly int i;
private readonly int j;
private readonly int k;
public C(int i, int j, int k)
{
this.i = i;
this.j = j;
this.k = k;
}
}"
,
index
:
3
);
}
[
WorkItem
(
35665
,
"https://github.com/dotnet/roslyn/issues/35665"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsInitializeParameter
)]
public
async
Task
TestGenerateRemainingFields2
()
{
await
TestInRegularAndScript1Async
(
@"
class C
{
private readonly int i;
public C(int i, [||]int j, int k)
{
this.i = i;
}
}"
,
@"
class C
{
private readonly int i;
private readonly int j;
private readonly int k;
public C(int i, int j, int k)
{
this.i = i;
this.j = j;
this.k = k;
}
}"
,
index
:
2
);
}
[
WorkItem
(
35665
,
"https://github.com/dotnet/roslyn/issues/35665"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsInitializeParameter
)]
public
async
Task
TestGenerateRemainingFields3
()
{
await
TestInRegularAndScript1Async
(
@"
class C
{
private readonly int j;
public C([||]int i, int j, int k)
{
this.j = j;
}
}"
,
@"
class C
{
private readonly int i;
private readonly int j;
private readonly int k;
public C(int i, int j, int k)
{
this.i = i;
this.j = j;
this.k = k;
}
}"
,
index
:
2
);
}
[
WorkItem
(
35665
,
"https://github.com/dotnet/roslyn/issues/35665"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsInitializeParameter
)]
public
async
Task
TestGenerateRemainingFields4
()
{
await
TestInRegularAndScript1Async
(
@"
class C
{
private readonly int k;
public C([||]int i, int j, int k)
{
this.k = k;
}
}"
,
@"
class C
{
private readonly int i;
private readonly int j;
private readonly int k;
public C(int i, int j, int k)
{
this.i = i;
this.j = j;
this.k = k;
}
}"
,
index
:
2
);
}
}
}
src/Features/CSharp/Portable/InitializeParameter/CSharpAddParameterCheckCodeRefactoringProvider.cs
浏览文件 @
ffad2b58
...
...
@@ -35,8 +35,8 @@ protected override SyntaxNode GetTypeBlock(SyntaxNode node)
protected
override
SyntaxNode
GetBody
(
SyntaxNode
functionDeclaration
)
=>
InitializeParameterHelpers
.
GetBody
(
functionDeclaration
);
protected
override
void
InsertStatement
(
SyntaxEditor
editor
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
metho
d
,
SyntaxNode
statementToAddAfterOpt
,
StatementSyntax
statement
)
=>
InitializeParameterHelpers
.
InsertStatement
(
editor
,
functionDeclaration
,
metho
d
,
statementToAddAfterOpt
,
statement
);
protected
override
void
InsertStatement
(
SyntaxEditor
editor
,
SyntaxNode
functionDeclaration
,
bool
returnsVoi
d
,
SyntaxNode
statementToAddAfterOpt
,
StatementSyntax
statement
)
=>
InitializeParameterHelpers
.
InsertStatement
(
editor
,
functionDeclaration
,
returnsVoi
d
,
statementToAddAfterOpt
,
statement
);
protected
override
bool
IsImplicitConversion
(
Compilation
compilation
,
ITypeSymbol
source
,
ITypeSymbol
destination
)
=>
InitializeParameterHelpers
.
IsImplicitConversion
(
compilation
,
source
,
destination
);
...
...
src/Features/CSharp/Portable/InitializeParameter/CSharpInitializeMemberFromParameterCodeRefactoringProvider.cs
浏览文件 @
ffad2b58
...
...
@@ -16,6 +16,7 @@ namespace Microsoft.CodeAnalysis.CSharp.InitializeParameter
[
ExtensionOrder
(
Before
=
PredefinedCodeRefactoringProviderNames
.
Wrapping
)]
internal
class
CSharpInitializeMemberFromParameterCodeRefactoringProvider
:
AbstractInitializeMemberFromParameterCodeRefactoringProvider
<
BaseTypeDeclarationSyntax
,
ParameterSyntax
,
StatementSyntax
,
ExpressionSyntax
>
...
...
@@ -34,8 +35,8 @@ protected override SyntaxNode GetTypeBlock(SyntaxNode node)
protected
override
SyntaxNode
TryGetLastStatement
(
IBlockOperation
blockStatementOpt
)
=>
InitializeParameterHelpers
.
TryGetLastStatement
(
blockStatementOpt
);
protected
override
void
InsertStatement
(
SyntaxEditor
editor
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
metho
d
,
SyntaxNode
statementToAddAfterOpt
,
StatementSyntax
statement
)
=>
InitializeParameterHelpers
.
InsertStatement
(
editor
,
functionDeclaration
,
metho
d
,
statementToAddAfterOpt
,
statement
);
protected
override
void
InsertStatement
(
SyntaxEditor
editor
,
SyntaxNode
functionDeclaration
,
bool
returnsVoi
d
,
SyntaxNode
statementToAddAfterOpt
,
StatementSyntax
statement
)
=>
InitializeParameterHelpers
.
InsertStatement
(
editor
,
functionDeclaration
,
returnsVoi
d
,
statementToAddAfterOpt
,
statement
);
protected
override
bool
IsImplicitConversion
(
Compilation
compilation
,
ITypeSymbol
source
,
ITypeSymbol
destination
)
=>
InitializeParameterHelpers
.
IsImplicitConversion
(
compilation
,
source
,
destination
);
...
...
src/Features/CSharp/Portable/InitializeParameter/InitializeParameterHelpers.cs
浏览文件 @
ffad2b58
...
...
@@ -62,7 +62,7 @@ public static SyntaxNode TryGetLastStatement(IBlockOperation blockStatementOpt)
public
static
void
InsertStatement
(
SyntaxEditor
editor
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
metho
d
,
bool
returnsVoi
d
,
SyntaxNode
statementToAddAfterOpt
,
StatementSyntax
statement
)
{
...
...
@@ -72,7 +72,7 @@ public static SyntaxNode TryGetLastStatement(IBlockOperation blockStatementOpt)
{
var
semicolonToken
=
TryGetSemicolonToken
(
functionDeclaration
)
??
SyntaxFactory
.
Token
(
SyntaxKind
.
SemicolonToken
);
if
(!
TryConvertExpressionBodyToStatement
(
body
,
semicolonToken
,
!
method
.
R
eturnsVoid
,
out
var
convertedStatement
))
if
(!
TryConvertExpressionBodyToStatement
(
body
,
semicolonToken
,
!
r
eturnsVoid
,
out
var
convertedStatement
))
{
return
;
}
...
...
src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs
浏览文件 @
ffad2b58
...
...
@@ -345,7 +345,7 @@ private bool IsNullCheck(IOperation operand1, IOperation operand2, IParameterSym
// signature.
var
statementToAddAfter
=
GetStatementToAddNullCheckAfter
(
semanticModel
,
parameter
,
blockStatementOpt
,
cancellationToken
);
InsertStatement
(
editor
,
functionDeclaration
,
method
,
statementToAddAfter
,
nullCheckStatement
);
InsertStatement
(
editor
,
functionDeclaration
,
method
.
ReturnsVoid
,
statementToAddAfter
,
nullCheckStatement
);
var
newRoot
=
editor
.
GetChangedRoot
();
return
document
.
WithSyntaxRoot
(
newRoot
);
...
...
src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs
浏览文件 @
ffad2b58
...
...
@@ -5,9 +5,9 @@
#
nullable
enable
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Diagnostics.CodeAnalysis
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
...
...
@@ -28,12 +28,14 @@
namespace
Microsoft.CodeAnalysis.InitializeParameter
{
internal
abstract
partial
class
AbstractInitializeMemberFromParameterCodeRefactoringProvider
<
TTypeDeclarationSyntax
,
TParameterSyntax
,
TStatementSyntax
,
TExpressionSyntax
>
:
AbstractInitializeParameterCodeRefactoringProvider
<
TParameterSyntax
,
TStatementSyntax
,
TExpressionSyntax
>
where
TTypeDeclarationSyntax
:
SyntaxNode
where
TParameterSyntax
:
SyntaxNode
where
TStatementSyntax
:
SyntaxNode
where
TExpressionSyntax
:
SyntaxNode
...
...
@@ -52,23 +54,22 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
}
protected
override
async
Task
<
ImmutableArray
<
CodeAction
>>
GetRefactoringsForSingleParameterAsync
(
Document
document
,
IParameterSymbol
parameter
,
SyntaxNode
function
Declaration
,
IMethodSymbol
method
,
Document
document
,
IParameterSymbol
parameter
,
SyntaxNode
constructor
Declaration
,
IMethodSymbol
method
,
IBlockOperation
?
blockStatementOpt
,
CancellationToken
cancellationToken
)
{
// Only supported for constructor parameters.
if
(
method
.
MethodKind
!=
MethodKind
.
Constructor
)
{
return
ImmutableArray
<
CodeAction
>.
Empty
;
}
var
assignmentStatement
=
TryFindFieldOrPropertyAssignmentStatement
(
parameter
,
blockStatementOpt
);
var
containingType
=
constructorDeclaration
.
GetAncestor
<
TTypeDeclarationSyntax
>();
if
(
containingType
==
null
)
return
ImmutableArray
<
CodeAction
>.
Empty
;
// See if we're already assigning this parameter to a field/property in this type. If so, there's nothing
// more for us to do.
var
assignmentStatement
=
TryFindFieldOrPropertyAssignmentStatement
(
parameter
,
blockStatementOpt
);
if
(
assignmentStatement
!=
null
)
{
// We're already assigning this parameter to a field/property in this type.
// So there's nothing more for us to do.
return
ImmutableArray
<
CodeAction
>.
Empty
;
}
// Haven't initialized any fields/properties with this parameter. Offer to assign
// to an existing matching field/prop if we can find one, or add a new field/prop
...
...
@@ -85,19 +86,19 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
if
(
fieldOrProperty
!=
null
)
{
return
HandleExistingFieldOrProperty
(
document
,
parameter
,
functionDeclaration
,
method
,
blockStatementOpt
,
fieldOrProperty
);
document
,
parameter
,
constructorDeclaration
,
method
,
blockStatementOpt
,
fieldOrProperty
);
}
return
await
HandleNoExistingFieldOrPropertyAsync
(
document
,
parameter
,
functionDeclaration
,
method
,
blockStatementOpt
,
rules
,
cancellationToken
).
ConfigureAwait
(
false
);
document
,
parameter
,
constructorDeclaration
,
method
,
blockStatementOpt
,
rules
,
cancellationToken
).
ConfigureAwait
(
false
);
}
private
async
Task
<
ImmutableArray
<
CodeAction
>>
HandleNoExistingFieldOrPropertyAsync
(
Document
document
,
IParameterSymbol
parameter
,
SyntaxNode
function
Declaration
,
SyntaxNode
constructor
Declaration
,
IMethodSymbol
method
,
IBlockOperation
?
blockStatementOpt
,
ImmutableArray
<
NamingRule
>
rules
,
...
...
@@ -110,7 +111,7 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
var
options
=
await
document
.
GetOptionsAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
(
fieldAction
,
propertyAction
)
=
AddSpecificParameterInitializationActions
(
document
,
parameter
,
functionDeclaration
,
method
,
blockStatementOpt
,
rules
,
options
);
document
,
parameter
,
constructorDeclaration
,
blockStatementOpt
,
rules
,
options
);
// Check if the surrounding parameters are assigned to another field in this class. If so, offer to
// make this parameter into a field as well. Otherwise, default to generating a property
...
...
@@ -127,7 +128,7 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
}
var
(
allFieldsAction
,
allPropertiesAction
)
=
AddAllParameterInitializationActions
(
document
,
function
Declaration
,
method
,
blockStatementOpt
,
rules
,
options
);
document
,
constructor
Declaration
,
method
,
blockStatementOpt
,
rules
,
options
);
if
(
allFieldsAction
!=
null
&&
allPropertiesAction
!=
null
)
{
...
...
@@ -148,7 +149,7 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
private
(
CodeAction
?
fieldAction
,
CodeAction
?
propertyAction
)
AddAllParameterInitializationActions
(
Document
document
,
SyntaxNode
function
Declaration
,
SyntaxNode
constructor
Declaration
,
IMethodSymbol
method
,
IBlockOperation
?
blockStatementOpt
,
ImmutableArray
<
NamingRule
>
rules
,
...
...
@@ -168,11 +169,11 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
var
allFieldsAction
=
new
MyCodeAction
(
FeaturesResources
.
Create_and_initialize_remaining_fields
,
c
=>
AddAllSymbolInitializationsAsync
(
document
,
functionDeclaration
,
method
,
blockStatementOpt
,
parameters
,
fields
,
c
));
document
,
constructorDeclaration
,
blockStatementOpt
,
parameters
,
fields
,
c
));
var
allPropertiesAction
=
new
MyCodeAction
(
FeaturesResources
.
Create_and_initialize_remaining_properties
,
c
=>
AddAllSymbolInitializationsAsync
(
document
,
functionDeclaration
,
method
,
blockStatementOpt
,
parameters
,
properties
,
c
));
document
,
constructorDeclaration
,
blockStatementOpt
,
parameters
,
properties
,
c
));
return
(
allFieldsAction
,
allPropertiesAction
);
}
...
...
@@ -180,8 +181,7 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
private
(
CodeAction
fieldAction
,
CodeAction
propertyAction
)
AddSpecificParameterInitializationActions
(
Document
document
,
IParameterSymbol
parameter
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
method
,
SyntaxNode
constructorDeclaration
,
IBlockOperation
?
blockStatementOpt
,
ImmutableArray
<
NamingRule
>
rules
,
DocumentOptionSet
options
)
...
...
@@ -190,10 +190,10 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
var
property
=
CreateProperty
(
parameter
,
options
,
rules
);
var
fieldAction
=
new
MyCodeAction
(
string
.
Format
(
FeaturesResources
.
Create_and_initialize_field_0
,
field
.
Name
),
c
=>
AddS
ymbolInitializationAsync
(
document
,
functionDeclaration
,
method
,
blockStatementOpt
,
parameter
,
field
,
c
));
c
=>
AddS
ingleSymbolInitializationAsync
(
document
,
constructorDeclaration
,
blockStatementOpt
,
parameter
,
field
,
c
));
var
propertyAction
=
new
MyCodeAction
(
string
.
Format
(
FeaturesResources
.
Create_and_initialize_property_0
,
property
.
Name
),
c
=>
AddS
ymbolInitializationAsync
(
document
,
functionDeclaration
,
method
,
blockStatementOpt
,
parameter
,
property
,
c
));
c
=>
AddS
ingleSymbolInitializationAsync
(
document
,
constructorDeclaration
,
blockStatementOpt
,
parameter
,
property
,
c
));
return
(
fieldAction
,
propertyAction
);
}
...
...
@@ -234,8 +234,8 @@ private ImmutableArray<CodeAction> HandleExistingFieldOrProperty(Document docume
return
ImmutableArray
.
Create
<
CodeAction
>(
new
MyCodeAction
(
title
,
c
=>
AddSymbolInitializationAsync
(
document
,
functionDeclaration
,
method
,
blockStatementOpt
,
parameter
,
fieldOrProperty
,
c
)));
c
=>
AddS
ingleS
ymbolInitializationAsync
(
document
,
functionDeclaration
,
blockStatementOpt
,
parameter
,
fieldOrProperty
,
c
)));
}
private
ISymbol
?
TryFindSiblingFieldOrProperty
(
IParameterSymbol
parameter
,
IBlockOperation
?
blockStatementOpt
)
...
...
@@ -250,22 +250,6 @@ private ImmutableArray<CodeAction> HandleExistingFieldOrProperty(Document docume
return
null
;
}
private
string
GetFieldName
(
IParameterSymbol
parameter
,
ImmutableArray
<
NamingRule
>
rules
,
ImmutableArray
<
string
>
parameterNameParts
)
{
foreach
(
var
rule
in
rules
)
{
if
(
rule
.
SymbolSpecification
.
AppliesTo
(
SymbolKind
.
Field
,
Accessibility
.
Private
))
return
GenerateUniqueName
(
parameter
,
parameterNameParts
,
rule
);
}
// We place a special rule in s_builtInRules that matches all fields. So we should
// always find a matching rule.
throw
ExceptionUtilities
.
Unreachable
;
}
private
IFieldSymbol
CreateField
(
IParameterSymbol
parameter
,
DocumentOptionSet
options
,
...
...
@@ -364,54 +348,88 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr
throw
ExceptionUtilities
.
Unreachable
;
}
private
Task
<
Document
>
AddSymbolInitializationAsync
(
Document
document
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
method
,
IBlockOperation
?
blockStatementOpt
,
IParameterSymbol
parameter
,
ISymbol
fieldOrProperty
,
CancellationToken
cancellationToken
)
{
return
AddAllSymbolInitializationsAsync
(
document
,
functionDeclaration
,
method
,
blockStatementOpt
,
ImmutableArray
.
Create
(
parameter
),
ImmutableArray
.
Create
(
fieldOrProperty
),
cancellationToken
);
}
private
async
Task
<
Document
>
AddAllSymbolInitializationsAsync
(
Document
document
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
method
,
SyntaxNode
constructorDeclaration
,
IBlockOperation
?
blockStatementOpt
,
ImmutableArray
<
IParameterSymbol
>
parameters
,
ImmutableArray
<
ISymbol
>
fieldsOrProperties
,
CancellationToken
cancellationToken
)
{
Debug
.
Assert
(
parameters
.
Length
>
0
);
Debug
.
Assert
(
parameters
.
Length
>
=
2
);
Debug
.
Assert
(
fieldsOrProperties
.
Length
>
0
);
Debug
.
Assert
(
parameters
.
Length
==
fieldsOrProperties
.
Length
);
// Process each param+field/prop in order. Apply the pair to the document getting the updated document.
// Then find all the current data in that updated document and move onto the next pair.
var
root
=
await
document
.
GetRequiredSyntaxRootAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
nodesToTrack
=
new
List
<
SyntaxNode
>
{
constructorDeclaration
};
if
(
blockStatementOpt
!=
null
)
nodesToTrack
.
Add
(
blockStatementOpt
.
Syntax
);
var
trackedRoot
=
root
.
TrackNodes
(
nodesToTrack
);
var
currentDocument
=
document
.
WithSyntaxRoot
(
trackedRoot
);
for
(
int
i
=
0
;
i
<
parameters
.
Length
;
i
++)
{
var
parameter
=
parameters
[
i
];
var
fieldOrProperty
=
fieldsOrProperties
[
i
];
var
currentSemanticModel
=
await
currentDocument
.
GetRequiredSemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
currentCompilation
=
currentSemanticModel
.
Compilation
;
var
currentRoot
=
await
currentDocument
.
GetRequiredSyntaxRootAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
currentConstructorDeclaration
=
currentRoot
.
GetCurrentNode
(
constructorDeclaration
);
if
(
currentConstructorDeclaration
==
null
)
continue
;
IBlockOperation
?
currentBlockStatementOpt
=
null
;
if
(
blockStatementOpt
!=
null
)
{
currentBlockStatementOpt
=
(
IBlockOperation
?)
currentSemanticModel
.
GetOperation
(
currentRoot
.
GetCurrentNode
(
blockStatementOpt
.
Syntax
));
if
(
currentBlockStatementOpt
==
null
)
continue
;
}
var
currentParameter
=
(
IParameterSymbol
?)
parameter
.
GetSymbolKey
(
cancellationToken
).
Resolve
(
currentCompilation
,
cancellationToken
:
cancellationToken
).
GetAnySymbol
();
if
(
currentParameter
==
null
)
continue
;
// fieldOrProperty is a new member. So we don't have to track it to this edit we're making.
currentDocument
=
await
AddSingleSymbolInitializationAsync
(
currentDocument
,
currentConstructorDeclaration
,
currentBlockStatementOpt
,
currentParameter
,
fieldOrProperty
,
cancellationToken
).
ConfigureAwait
(
false
);
}
return
currentDocument
;
}
private
async
Task
<
Document
>
AddSingleSymbolInitializationAsync
(
Document
document
,
SyntaxNode
constructorDeclaration
,
IBlockOperation
?
blockStatementOpt
,
IParameterSymbol
parameter
,
ISymbol
fieldOrProperty
,
CancellationToken
cancellationToken
)
{
var
workspace
=
document
.
Project
.
Solution
.
Workspace
;
var
root
=
await
document
.
GetSyntaxRootAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
editor
=
new
SyntaxEditor
(
root
,
workspace
);
var
generator
=
editor
.
Generator
;
var
containingType
=
fieldsOrProperties
[
0
].
ContainingType
;
if
(
containingType
==
null
)
if
(
fieldOrProperty
.
ContainingType
==
null
)
{
// We're generating a new field/property. Place into the containing type,
// ideally before/after a relevant existing member.
// First, look for the right containing type (As a type may be partial).
// We want the type-block that this constructor is contained within.
var
firstParameter
=
parameters
.
First
();
var
typeDeclaration
=
firstParameter
.
ContainingType
.
DeclaringSyntaxReferences
.
Select
(
r
=>
GetTypeBlock
(
r
.
GetSyntax
(
cancellationToken
)))
.
Single
(
d
=>
functionDeclaration
.
Ancestors
().
Contains
(
d
));
var
typeDeclaration
=
constructorDeclaration
.
GetAncestor
<
TTypeDeclarationSyntax
>()!;
// Now add the field/property to this type. Use the 'ReplaceNode+callback' form
// so that nodes will be appropriate tracked and so we can then update the constructor
...
...
@@ -425,48 +443,39 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr
typeDeclaration
,
(
currentTypeDecl
,
_
)
=>
{
for
(
int
i
=
0
;
i
<
parameters
.
Length
;
i
++
)
if
(
fieldOrProperty
is
IPropertySymbol
property
)
{
var
parameter
=
parameters
[
i
];
var
fieldOrProperty
=
fieldsOrProperties
[
i
];
currentTypeDecl
=
fieldOrProperty
switch
{
IPropertySymbol
property
=>
CodeGenerator
.
AddPropertyDeclaration
(
currentTypeDecl
,
property
,
workspace
,
GetAddOptions
<
IPropertySymbol
>(
parameter
,
blockStatementOpt
,
typeDeclaration
,
cancellationToken
))
,
IFieldSymbol
field
=>
CodeGenerator
.
AddFieldDeclaration
(
currentTypeDecl
,
field
,
workspace
,
GetAddOptions
<
IFieldSymbol
>(
parameter
,
blockStatementOpt
,
typeDeclaration
,
cancellationToken
)),
_
=>
throw
ExceptionUtilities
.
Unreachable
,
}
;
return
CodeGenerator
.
AddPropertyDeclaration
(
currentTypeDecl
,
property
,
workspace
,
GetAddOptions
<
IPropertySymbol
>(
parameter
,
blockStatementOpt
,
typeDeclaration
,
cancellationToken
));
}
else
if
(
fieldOrProperty
is
IFieldSymbol
field
)
{
return
CodeGenerator
.
AddFieldDeclaration
(
currentTypeDecl
,
field
,
workspace
,
GetAddOptions
<
IFieldSymbol
>(
parameter
,
blockStatementOpt
,
typeDeclaration
,
cancellationToken
));
}
else
{
throw
ExceptionUtilities
.
Unreachable
;
}
return
currentTypeDecl
;
});
}
for
(
int
i
=
0
;
i
<
parameters
.
Length
;
i
++)
{
var
parameter
=
parameters
[
i
];
var
fieldOrProperty
=
fieldsOrProperties
[
i
];
// Now that we've added any potential members, create an assignment between it
// and the parameter.
var
initializationStatement
=
(
TStatementSyntax
)
generator
.
ExpressionStatement
(
generator
.
AssignmentStatement
(
generator
.
MemberAccessExpression
(
generator
.
ThisExpression
(),
generator
.
IdentifierName
(
fieldOrProperty
.
Name
)),
generator
.
IdentifierName
(
parameter
.
Name
)));
// Attempt to place the initialization in a good location in the constructor
// We'll want to keep initialization statements in the same order as we see
// parameters for the constructor.
var
statementToAddAfterOpt
=
TryGetStatementToAddInitializationAfter
(
parameter
,
blockStatementOpt
);
InsertStatement
(
editor
,
functionDeclaration
,
method
,
statementToAddAfterOpt
,
initializationStatement
);
}
// Now that we've added any potential members, create an assignment between it
// and the parameter.
var
initializationStatement
=
(
TStatementSyntax
)
generator
.
ExpressionStatement
(
generator
.
AssignmentStatement
(
generator
.
MemberAccessExpression
(
generator
.
ThisExpression
(),
generator
.
IdentifierName
(
fieldOrProperty
.
Name
)),
generator
.
IdentifierName
(
parameter
.
Name
)));
// Attempt to place the initialization in a good location in the constructor
// We'll want to keep initialization statements in the same order as we see
// parameters for the constructor.
var
statementToAddAfterOpt
=
TryGetStatementToAddInitializationAfter
(
parameter
,
blockStatementOpt
);
InsertStatement
(
editor
,
constructorDeclaration
,
returnsVoid
:
true
,
statementToAddAfterOpt
,
initializationStatement
);
return
document
.
WithSyntaxRoot
(
editor
.
GetChangedRoot
());
}
...
...
@@ -484,23 +493,19 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr
if
(
statement
!=
null
&&
fieldOrProperty
is
TSymbol
symbol
)
{
if
(
before
)
var
symbolSyntax
=
symbol
.
DeclaringSyntaxReferences
[
0
].
GetSyntax
(
cancellationToken
);
if
(
symbolSyntax
.
Ancestors
().
Contains
(
typeDeclaration
))
{
var
symbolSyntax
=
symbol
.
DeclaringSyntaxReferences
[
0
].
GetSyntax
(
cancellationToken
);
if
(
symbolSyntax
.
Ancestors
().
Contains
(
typeDeclaration
))
if
(
before
)
{
// Found an existing field/property that corresponds to a preceding parameter.
// Place ourselves directly after it.
return
new
CodeGenerationOptions
(
afterThisLocation
:
symbolSyntax
.
GetLocation
());
}
}
else
{
// Found an existing field/property that corresponds to a following parameter.
// Place ourselves directly before it.
var
symbolSyntax
=
symbol
.
DeclaringSyntaxReferences
[
0
].
GetSyntax
(
cancellationToken
);
if
(
symbolSyntax
.
Ancestors
().
Contains
(
typeDeclaration
))
else
{
// Found an existing field/property that corresponds to a following parameter.
// Place ourselves directly before it.
return
new
CodeGenerationOptions
(
beforeThisLocation
:
symbolSyntax
.
GetLocation
());
}
}
...
...
src/Features/Core/Portable/InitializeParameter/AbstractInitializeParameterCodeRefactoringProvider.cs
浏览文件 @
ffad2b58
...
...
@@ -53,7 +53,7 @@ internal abstract partial class AbstractInitializeParameterCodeRefactoringProvid
CancellationToken
cancellationToken
);
protected
abstract
void
InsertStatement
(
SyntaxEditor
editor
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
metho
d
,
SyntaxEditor
editor
,
SyntaxNode
functionDeclaration
,
bool
returnsVoi
d
,
SyntaxNode
?
statementToAddAfterOpt
,
TStatementSyntax
statement
);
public
override
async
Task
ComputeRefactoringsAsync
(
CodeRefactoringContext
context
)
...
...
src/Features/VisualBasic/Portable/InitializeParameter/VisualBasicAddParameterCheckCodeRefactoringProvider.vb
浏览文件 @
ffad2b58
...
...
@@ -35,7 +35,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InitializeParameter
Return
InitializeParameterHelpers
.
GetBody
(
functionDeclaration
)
End
Function
Protected
Overrides
Sub
InsertStatement
(
editor
As
SyntaxEditor
,
functionDeclaration
As
SyntaxNode
,
method
As
IMethodSymbol
,
statementToAddAfterOpt
As
SyntaxNode
,
statement
As
StatementSyntax
)
Protected
Overrides
Sub
InsertStatement
(
editor
As
SyntaxEditor
,
functionDeclaration
As
SyntaxNode
,
returnsVoid
As
Boolean
,
statementToAddAfterOpt
As
SyntaxNode
,
statement
As
StatementSyntax
)
InitializeParameterHelpers
.
InsertStatement
(
editor
,
functionDeclaration
,
statementToAddAfterOpt
,
statement
)
End
Sub
...
...
src/Features/VisualBasic/Portable/InitializeParameter/VisualBasicInitializeMemberFromParameterCodeRefactoringProvider.vb
浏览文件 @
ffad2b58
...
...
@@ -15,6 +15,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InitializeParameter
<
ExtensionOrder
(
Before
:
=
PredefinedCodeRefactoringProviderNames
.
Wrapping
)
>
Friend
Class
VisualBasicInitializeMemberFromParameterCodeRefactoringProvider
Inherits
AbstractInitializeMemberFromParameterCodeRefactoringProvider
(
Of
TypeBlockSyntax
,
ParameterSyntax
,
StatementSyntax
,
ExpressionSyntax
)
...
...
@@ -39,7 +40,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.InitializeParameter
Return
InitializeParameterHelpers
.
IsImplicitConversion
(
compilation
,
source
,
destination
)
End
Function
Protected
Overrides
Sub
InsertStatement
(
editor
As
SyntaxEditor
,
functionDeclaration
As
SyntaxNode
,
method
As
IMethodSymbol
,
statementToAddAfterOpt
As
SyntaxNode
,
statement
As
StatementSyntax
)
Protected
Overrides
Sub
InsertStatement
(
editor
As
SyntaxEditor
,
functionDeclaration
As
SyntaxNode
,
returnsVoid
As
Boolean
,
statementToAddAfterOpt
As
SyntaxNode
,
statement
As
StatementSyntax
)
InitializeParameterHelpers
.
InsertStatement
(
editor
,
functionDeclaration
,
statementToAddAfterOpt
,
statement
)
End
Sub
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录