Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
ca0f2582
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,发现更多精彩内容 >>
提交
ca0f2582
编写于
3月 21, 2020
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Follow user style when generating fields from parameters.
上级
423c52f2
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
186 addition
and
86 deletion
+186
-86
src/EditorFeatures/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs
...InitializeParameter/InitializeMemberFromParameterTests.cs
+58
-0
src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs
...mberFromParameterCodeRefactoringProviderMemberCreation.cs
+106
-70
src/Features/Core/Portable/InitializeParameter/AbstractInitializeParameterCodeRefactoringProvider.cs
...ter/AbstractInitializeParameterCodeRefactoringProvider.cs
+22
-16
未找到文件。
src/EditorFeatures/CSharpTest/InitializeParameter/InitializeMemberFromParameterTests.cs
浏览文件 @
ca0f2582
...
...
@@ -1560,5 +1560,63 @@ class C
public string S { get; }
}"
,
options
:
this
.
Option
(
CSharpFormattingOptions
.
NewLinesForBracesInMethods
,
false
));
}
[
WorkItem
(
23308
,
"https://github.com/dotnet/roslyn/issues/23308"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsInitializeParameter
)]
public
async
Task
TestGenerateFieldIfParameterFollowsExistingFieldAssignment
()
{
await
TestInRegularAndScript1Async
(
@"
class C
{
private readonly string s;
public C(string s, [||]int i)
{
this.s = s;
}
}"
,
@"
class C
{
private readonly string s;
private readonly int i;
public C(string s, int i)
{
this.s = s;
this.i = i;
}
}"
);
}
[
WorkItem
(
23308
,
"https://github.com/dotnet/roslyn/issues/23308"
)]
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsInitializeParameter
)]
public
async
Task
TestGenerateFieldIfParameterPrecedesExistingFieldAssignment
()
{
await
TestInRegularAndScript1Async
(
@"
class C
{
private readonly string s;
public C([||]int i, string s)
{
this.s = s;
}
}"
,
@"
class C
{
private readonly int i;
private readonly string s;
public C(int i, string s)
{
this.i = i;
this.s = s;
}
}"
);
}
}
}
src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs
浏览文件 @
ca0f2582
...
...
@@ -2,7 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System
;
using
System.Collections.Immutable
;
using
System.Diagnostics.CodeAnalysis
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
...
...
@@ -12,6 +16,7 @@
using
Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles
;
using
Microsoft.CodeAnalysis.Editing
;
using
Microsoft.CodeAnalysis.Operations
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Shared.Naming
;
using
Microsoft.CodeAnalysis.Shared.Utilities
;
...
...
@@ -31,20 +36,22 @@ internal abstract partial class AbstractInitializeMemberFromParameterCodeRefacto
where
TStatementSyntax
:
SyntaxNode
where
TExpressionSyntax
:
SyntaxNode
{
protected
abstract
SyntaxNode
TryGetLastStatement
(
IBlockOperation
blockStatementOpt
);
protected
abstract
SyntaxNode
TryGetLastStatement
(
IBlockOperation
?
blockStatementOpt
);
protected
abstract
Accessibility
DetermineDefaultFieldAccessibility
(
INamedTypeSymbol
containingType
);
protected
abstract
Accessibility
DetermineDefaultPropertyAccessibility
();
protected
override
Task
<
ImmutableArray
<
CodeAction
>>
GetRefactoringsForAllParametersAsync
(
Document
document
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
method
,
IBlockOperation
blockStatementOpt
,
ImmutableArray
<
SyntaxNode
>
listOfParameterNodes
,
TextSpan
parameterSpan
,
CancellationToken
cancellationToken
)
protected
override
Task
<
ImmutableArray
<
CodeAction
>>
GetRefactoringsForAllParametersAsync
(
Document
document
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
method
,
IBlockOperation
?
blockStatementOpt
,
ImmutableArray
<
SyntaxNode
>
listOfParameterNodes
,
TextSpan
parameterSpan
,
CancellationToken
cancellationToken
)
{
return
Task
.
FromResult
(
ImmutableArray
<
CodeAction
>.
Empty
);
}
protected
override
async
Task
<
ImmutableArray
<
CodeAction
>>
GetRefactoringsForSingleParameterAsync
(
Document
document
,
IParameterSymbol
parameter
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
method
,
IBlockOperation
blockStatementOpt
,
CancellationToken
cancellationToken
)
IBlockOperation
?
blockStatementOpt
,
CancellationToken
cancellationToken
)
{
// Only supported for constructor parameters.
if
(
method
.
MethodKind
!=
MethodKind
.
Constructor
)
...
...
@@ -103,17 +110,40 @@ protected override Task<ImmutableArray<CodeAction>> GetRefactoringsForAllParamet
var
field
=
CreateField
(
requireAccessibilityModifiers
,
parameter
,
rules
,
parameterNameParts
.
BaseNameParts
);
var
property
=
CreateProperty
(
requireAccessibilityModifiers
,
parameter
,
rules
,
parameterNameParts
.
BaseNameParts
);
// Offer to generate either a property or a field. Currently we place the property
// suggestion first (to help users with the immutable object+property pattern). But
// we could consider swapping this if people prefer creating private fields more.
return
ImmutableArray
.
Create
<
CodeAction
>(
new
MyCodeAction
(
string
.
Format
(
FeaturesResources
.
Create_and_initialize_property_0
,
property
.
Name
),
c
=>
AddSymbolInitializationAsync
(
document
,
parameter
,
functionDeclaration
,
method
,
blockStatementOpt
,
property
,
c
)),
new
MyCodeAction
(
string
.
Format
(
FeaturesResources
.
Create_and_initialize_field_0
,
field
.
Name
),
c
=>
AddSymbolInitializationAsync
(
document
,
parameter
,
functionDeclaration
,
method
,
blockStatementOpt
,
field
,
c
)));
var
fieldAction
=
new
MyCodeAction
(
string
.
Format
(
FeaturesResources
.
Create_and_initialize_field_0
,
field
.
Name
),
c
=>
AddSymbolInitializationAsync
(
document
,
parameter
,
functionDeclaration
,
method
,
blockStatementOpt
,
field
,
c
));
var
propertyAction
=
new
MyCodeAction
(
string
.
Format
(
FeaturesResources
.
Create_and_initialize_property_0
,
property
.
Name
),
c
=>
AddSymbolInitializationAsync
(
document
,
parameter
,
functionDeclaration
,
method
,
blockStatementOpt
,
property
,
c
));
// 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.
var
siblingFieldOrProperty
=
TryFindSiblingFieldOrProperty
(
parameter
,
blockStatementOpt
);
if
(
siblingFieldOrProperty
is
IFieldSymbol
)
{
return
ImmutableArray
.
Create
<
CodeAction
>(
fieldAction
,
propertyAction
);
}
else
{
// Otherwise, default to generating a property
return
ImmutableArray
.
Create
<
CodeAction
>(
propertyAction
,
fieldAction
);
}
}
}
private
ISymbol
?
TryFindSiblingFieldOrProperty
(
IParameterSymbol
parameter
,
IBlockOperation
?
blockStatementOpt
)
{
foreach
(
var
(
siblingParam
,
_
)
in
GetSiblingParameters
(
parameter
))
{
TryFindFieldOrPropertyAssignmentStatement
(
siblingParam
,
blockStatementOpt
,
out
var
sibling
);
if
(
sibling
!=
null
)
return
sibling
;
}
return
null
;
}
private
IFieldSymbol
CreateField
(
CodeStyleOption
<
AccessibilityModifiersRequired
>
requireAccessibilityModifiers
,
IParameterSymbol
parameter
,
...
...
@@ -210,7 +240,7 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr
private
async
Task
<
Document
>
AddSymbolInitializationAsync
(
Document
document
,
IParameterSymbol
parameter
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
method
,
IBlockOperation
blockStatementOpt
,
ISymbol
fieldOrProperty
,
CancellationToken
cancellationToken
)
IBlockOperation
?
blockStatementOpt
,
ISymbol
fieldOrProperty
,
CancellationToken
cancellationToken
)
{
var
workspace
=
document
.
Project
.
Solution
.
Workspace
;
var
root
=
await
document
.
GetSyntaxRootAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
...
...
@@ -274,51 +304,45 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr
// parameters for the constructor.
var
statementToAddAfterOpt
=
TryGetStatementToAddInitializationAfter
(
parameter
,
blockStatementOpt
);
InsertStatement
(
editor
,
functionDeclaration
,
method
,
statementToAddAfterOpt
,
initializationStatement
);
InsertStatement
(
editor
,
functionDeclaration
,
method
,
statementToAddAfterOpt
,
initializationStatement
);
return
document
.
WithSyntaxRoot
(
editor
.
GetChangedRoot
());
}
private
CodeGenerationOptions
GetAddOptions
<
TSymbol
>(
IParameterSymbol
parameter
,
IBlockOperation
blockStatementOpt
,
private
CodeGenerationOptions
?
GetAddOptions
<
TSymbol
>(
IParameterSymbol
parameter
,
IBlockOperation
?
blockStatementOpt
,
SyntaxNode
typeDeclaration
,
CancellationToken
cancellationToken
)
where
TSymbol
:
ISymbol
{
var
methodSymbol
=
(
IMethodSymbol
)
parameter
.
ContainingSymbol
;
var
parameterIndex
=
methodSymbol
.
Parameters
.
IndexOf
(
parameter
);
for
(
var
i
=
parameterIndex
-
1
;
i
>=
0
;
i
--)
foreach
(
var
(
sibling
,
before
)
in
GetSiblingParameters
(
parameter
))
{
var
statement
=
TryFindFieldOrPropertyAssignmentStatement
(
methodSymbol
.
Parameters
[
i
]
,
blockStatementOpt
,
out
var
fieldOrProperty
);
sibling
,
blockStatementOpt
,
out
var
fieldOrProperty
);
if
(
statement
!=
null
&&
fieldOrProperty
is
TSymbol
symbol
)
{
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
());
var
symbolSyntax
=
symbol
.
DeclaringSyntaxReferences
[
0
].
GetSyntax
(
cancellationToken
);
if
(
symbolSyntax
.
Ancestors
().
Contains
(
typeDeclaration
))
{
// Found an existing field/property that corresponds to a preceding parameter.
// Place ourselves directly after it.
return
new
CodeGenerationOptions
(
afterThisLocation
:
symbolSyntax
.
GetLocation
());
}
}
}
}
for
(
var
i
=
parameterIndex
+
1
;
i
<
methodSymbol
.
Parameters
.
Length
;
i
++)
{
var
statement
=
TryFindFieldOrPropertyAssignmentStatement
(
methodSymbol
.
Parameters
[
i
],
blockStatementOpt
,
out
var
fieldOrProperty
);
if
(
statement
!=
null
&&
fieldOrProperty
is
TSymbol
symbol
)
{
// 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
{
return
new
CodeGenerationOptions
(
beforeThisLocation
:
symbolSyntax
.
GetLocation
());
// 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
))
{
return
new
CodeGenerationOptions
(
beforeThisLocation
:
symbolSyntax
.
GetLocation
());
}
}
}
}
...
...
@@ -326,34 +350,47 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr
return
null
;
}
private
SyntaxNode
TryGetStatementToAddInitializationAfter
(
IParameterSymbol
parameter
,
IBlockOperation
blockStatementOpt
)
private
ImmutableArray
<(
IParameterSymbol
parameter
,
bool
before
)>
GetSiblingParameters
(
IParameterSymbol
parameter
)
{
var
methodSymbol
=
(
IMethodSymbol
)
parameter
.
ContainingSymbol
;
var
parameterIndex
=
methodSymbol
.
Parameters
.
IndexOf
(
parameter
);
using
var
_
=
ArrayBuilder
<(
IParameterSymbol
,
bool
)>.
GetInstance
(
out
var
siblings
);
// look for an existing assignment for a parameter that comes before us.
// If we find one, we'll add ourselves after that parameter check.
for
(
var
i
=
parameterIndex
-
1
;
i
>=
0
;
i
--)
if
(
parameter
.
ContainingSymbol
is
IMethodSymbol
method
)
{
var
statement
=
TryFindFieldOrPropertyAssignmentStatement
(
methodSymbol
.
Parameters
[
i
],
blockStatementOpt
);
if
(
statement
!=
null
)
{
return
statement
.
Syntax
;
}
var
parameterIndex
=
method
.
Parameters
.
IndexOf
(
parameter
);
// look for an existing assignment for a parameter that comes before us.
// If we find one, we'll add ourselves after that parameter check.
for
(
var
i
=
parameterIndex
-
1
;
i
>=
0
;
i
--)
siblings
.
Add
((
method
.
Parameters
[
i
],
true
));
// look for an existing check for a parameter that comes before us.
// If we find one, we'll add ourselves after that parameter check.
for
(
var
i
=
parameterIndex
+
1
;
i
<
method
.
Parameters
.
Length
;
i
++)
siblings
.
Add
((
method
.
Parameters
[
i
],
false
));
}
// look for an existing check for a parameter that comes before us.
// If we find one, we'll add ourselves after that parameter check.
for
(
var
i
=
parameterIndex
+
1
;
i
<
methodSymbol
.
Parameters
.
Length
;
i
++)
return
siblings
.
ToImmutable
();
}
private
SyntaxNode
?
TryGetStatementToAddInitializationAfter
(
IParameterSymbol
parameter
,
IBlockOperation
?
blockStatementOpt
)
{
// look for an existing assignment for a parameter that comes before/after us.
// If we find one, we'll add ourselves before/after that parameter check.
foreach
(
var
(
sibling
,
before
)
in
GetSiblingParameters
(
parameter
))
{
var
statement
=
TryFindFieldOrPropertyAssignmentStatement
(
methodSymbol
.
Parameters
[
i
],
blockStatementOpt
);
var
statement
=
TryFindFieldOrPropertyAssignmentStatement
(
sibling
,
blockStatementOpt
);
if
(
statement
!=
null
)
{
var
statementIndex
=
blockStatementOpt
.
Operations
.
IndexOf
(
statement
);
return
statementIndex
>
0
?
blockStatementOpt
.
Operations
[
statementIndex
-
1
].
Syntax
:
null
;
if
(
before
)
{
return
statement
.
Syntax
;
}
else
{
var
statementIndex
=
blockStatementOpt
!.
Operations
.
IndexOf
(
statement
);
return
statementIndex
>
0
?
blockStatementOpt
.
Operations
[
statementIndex
-
1
].
Syntax
:
null
;
}
}
}
...
...
@@ -362,11 +399,11 @@ private static string GenerateUniqueName(IParameterSymbol parameter, ImmutableAr
return
TryGetLastStatement
(
blockStatementOpt
);
}
private
IOperation
TryFindFieldOrPropertyAssignmentStatement
(
IParameterSymbol
parameter
,
IBlockOperation
blockStatementOpt
)
=>
TryFindFieldOrPropertyAssignmentStatement
(
parameter
,
blockStatementOpt
,
out
var
fieldOrProperty
);
private
IOperation
?
TryFindFieldOrPropertyAssignmentStatement
(
IParameterSymbol
parameter
,
IBlockOperation
?
blockStatementOpt
)
=>
TryFindFieldOrPropertyAssignmentStatement
(
parameter
,
blockStatementOpt
,
out
_
);
private
IOperation
TryFindFieldOrPropertyAssignmentStatement
(
IParameterSymbol
parameter
,
IBlockOperation
blockStatementOpt
,
out
ISymbol
fieldOrProperty
)
private
IOperation
?
TryFindFieldOrPropertyAssignmentStatement
(
IParameterSymbol
parameter
,
IBlockOperation
?
blockStatementOpt
,
out
ISymbol
?
fieldOrProperty
)
{
if
(
blockStatementOpt
!=
null
)
{
...
...
@@ -407,14 +444,14 @@ private IOperation TryFindFieldOrPropertyAssignmentStatement(IParameterSymbol pa
return
false
;
}
private
async
Task
<
ISymbol
>
TryFindMatchingUninitializedFieldOrPropertySymbolAsync
(
Document
document
,
IParameterSymbol
parameter
,
IBlockOperation
blockStatementOpt
,
ImmutableArray
<
NamingRule
>
rules
,
ImmutableArray
<
string
>
parameterWords
,
CancellationToken
cancellationToken
)
private
async
Task
<
ISymbol
?
>
TryFindMatchingUninitializedFieldOrPropertySymbolAsync
(
Document
document
,
IParameterSymbol
parameter
,
IBlockOperation
?
blockStatementOpt
,
ImmutableArray
<
NamingRule
>
rules
,
ImmutableArray
<
string
>
parameterWords
,
CancellationToken
cancellationToken
)
{
// Look for a field/property that really looks like it corresponds to this parameter.
// Use a variety of heuristics around the name/type to see if this is a match.
var
containingType
=
parameter
.
ContainingType
;
var
compilation
=
await
document
.
Project
.
GetCompilationAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
compilation
=
await
document
.
Project
.
Get
Required
CompilationAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
// Walk through the naming rules against this parameter's name to see what
// name the user would like for it as a member in this type. Note that we
...
...
@@ -439,7 +476,6 @@ private IOperation TryFindFieldOrPropertyAssignmentStatement(IParameterSymbol pa
return
field
;
}
// If it's a writable property that we could assign this parameter to, and it's
// not already been assigned to, then this property is a good candidate for us to
// hook up to.
...
...
@@ -459,7 +495,7 @@ private IOperation TryFindFieldOrPropertyAssignmentStatement(IParameterSymbol pa
}
private
bool
ContainsMemberAssignment
(
IBlockOperation
blockStatementOpt
,
ISymbol
member
)
IBlockOperation
?
blockStatementOpt
,
ISymbol
member
)
{
if
(
blockStatementOpt
!=
null
)
{
...
...
src/Features/Core/Portable/InitializeParameter/AbstractInitializeParameterCodeRefactoringProvider.cs
浏览文件 @
ca0f2582
...
...
@@ -2,8 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#
nullable
enable
using
System
;
using
System.Collections.Immutable
;
using
System.Diagnostics.CodeAnalysis
;
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
...
...
@@ -36,7 +39,7 @@ internal abstract partial class AbstractInitializeParameterCodeRefactoringProvid
Document
document
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
method
,
IBlockOperation
blockStatementOpt
,
IBlockOperation
?
blockStatementOpt
,
ImmutableArray
<
SyntaxNode
>
listOfParameterNodes
,
TextSpan
parameterSpan
,
CancellationToken
cancellationToken
);
...
...
@@ -46,12 +49,12 @@ internal abstract partial class AbstractInitializeParameterCodeRefactoringProvid
IParameterSymbol
parameter
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
methodSymbol
,
IBlockOperation
blockStatementOpt
,
IBlockOperation
?
blockStatementOpt
,
CancellationToken
cancellationToken
);
protected
abstract
void
InsertStatement
(
SyntaxEditor
editor
,
SyntaxNode
functionDeclaration
,
IMethodSymbol
method
,
SyntaxNode
statementToAddAfterOpt
,
TStatementSyntax
statement
);
SyntaxNode
?
statementToAddAfterOpt
,
TStatementSyntax
statement
);
public
override
async
Task
ComputeRefactoringsAsync
(
CodeRefactoringContext
context
)
{
...
...
@@ -74,8 +77,8 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
var
generator
=
SyntaxGenerator
.
GetGenerator
(
document
);
var
parameterNodes
=
generator
.
GetParameters
(
functionDeclaration
);
var
semanticModel
=
await
document
.
GetSemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
syntaxFacts
=
document
.
GetLanguageService
<
ISyntaxFactsService
>();
var
semanticModel
=
await
document
.
Get
Required
SemanticModelAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
syntaxFacts
=
document
.
Get
Required
LanguageService
<
ISyntaxFactsService
>();
var
parameterDefault
=
syntaxFacts
.
GetDefaultOfParameter
(
selectedParameter
);
...
...
@@ -135,7 +138,9 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
}
}
protected
bool
CanOfferRefactoring
(
SyntaxNode
functionDeclaration
,
SemanticModel
semanticModel
,
ISyntaxFactsService
syntaxFacts
,
CancellationToken
cancellationToken
,
out
IBlockOperation
blockStatementOpt
)
protected
bool
CanOfferRefactoring
(
SyntaxNode
functionDeclaration
,
SemanticModel
semanticModel
,
ISyntaxFactsService
syntaxFacts
,
CancellationToken
cancellationToken
,
[
MaybeNullWhen
(
false
)]
out
IBlockOperation
?
blockStatementOpt
)
{
blockStatementOpt
=
null
;
...
...
@@ -193,26 +198,26 @@ protected static IOperation UnwrapImplicitConversion(IOperation operation)
foreach
(
var
child
in
condition
.
Syntax
.
DescendantNodes
().
OfType
<
TExpressionSyntax
>())
{
var
childOperation
=
semanticModel
.
GetOperation
(
child
,
cancellationToken
);
if
(
IsParameterReference
(
childOperation
,
parameter
))
{
if
(
childOperation
!=
null
&&
IsParameterReference
(
childOperation
,
parameter
))
return
true
;
}
}
return
false
;
}
protected
static
bool
IsFieldOrPropertyAssignment
(
IOperation
statement
,
INamedTypeSymbol
containingType
,
out
IAssignmentOperation
assignmentExpression
)
=>
IsFieldOrPropertyAssignment
(
statement
,
containingType
,
out
assignmentExpression
,
out
var
fieldOrProperty
);
protected
static
bool
IsFieldOrPropertyAssignment
(
IOperation
statement
,
INamedTypeSymbol
containingType
,
[
NotNullWhen
(
true
)]
out
IAssignmentOperation
?
assignmentExpression
)
=>
IsFieldOrPropertyAssignment
(
statement
,
containingType
,
out
assignmentExpression
,
out
_
);
protected
static
bool
IsFieldOrPropertyAssignment
(
IOperation
statement
,
INamedTypeSymbol
containingType
,
out
IAssignmentOperation
assignmentExpression
,
out
ISymbol
fieldOrProperty
)
[
NotNullWhen
(
true
)]
out
IAssignmentOperation
?
assignmentExpression
,
[
NotNullWhen
(
true
)]
out
ISymbol
?
fieldOrProperty
)
{
if
(
statement
is
IExpressionStatementOperation
expressionStatement
)
if
(
statement
is
IExpressionStatementOperation
expressionStatement
&&
expressionStatement
.
Operation
is
IAssignmentOperation
assignment
)
{
assignmentExpression
=
expressionStatement
.
Operation
as
IAssignmentOperation
;
return
IsFieldOrPropertyReference
(
assignmentExpression
?
.
Target
,
containingType
,
out
fieldOrProperty
);
assignmentExpression
=
assignment
;
return
IsFieldOrPropertyReference
(
assignmentExpression
.
Target
,
containingType
,
out
fieldOrProperty
);
}
fieldOrProperty
=
null
;
...
...
@@ -224,7 +229,8 @@ protected static bool IsFieldOrPropertyReference(IOperation operation, INamedTyp
=>
IsFieldOrPropertyAssignment
(
operation
,
containingType
,
out
var
fieldOrProperty
);
protected
static
bool
IsFieldOrPropertyReference
(
IOperation
operation
,
INamedTypeSymbol
containingType
,
out
ISymbol
fieldOrProperty
)
IOperation
?
operation
,
INamedTypeSymbol
containingType
,
[
NotNullWhen
(
true
)]
out
ISymbol
?
fieldOrProperty
)
{
if
(
operation
is
IMemberReferenceOperation
memberReference
&&
memberReference
.
Member
.
ContainingType
.
Equals
(
containingType
))
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录