Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
3a3029d8
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,发现更多精彩内容 >>
未验证
提交
3a3029d8
编写于
4月 29, 2020
作者:
C
CyrusNajmabadi
提交者:
GitHub
4月 29, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #43771 from CyrusNajmabadi/convertTupleToStructOOP
Move convert tuple to struct oop
上级
1b17eae2
90e1aa88
变更
13
展开全部
隐藏空白更改
内联
并排
Showing
13 changed file
with
497 addition
and
271 deletion
+497
-271
src/EditorFeatures/CSharpTest/ConvertTupleToStruct/ConvertTupleToStructTests.cs
...arpTest/ConvertTupleToStruct/ConvertTupleToStructTests.cs
+128
-111
src/EditorFeatures/VisualBasicTest/ConvertTupleToStruct/ConvertTupleToStructTests.vb
...sicTest/ConvertTupleToStruct/ConvertTupleToStructTests.vb
+108
-97
src/Features/CSharp/Portable/ConvertTupleToStruct/CSharpConvertTupleToStructCodeRefactoringProvider.cs
...ruct/CSharpConvertTupleToStructCodeRefactoringProvider.cs
+2
-7
src/Features/Core/Portable/ConvertTupleToStruct/AbstractConvertTupleToStructCodeRefactoringProvider.cs
...ct/AbstractConvertTupleToStructCodeRefactoringProvider.cs
+92
-47
src/Features/Core/Portable/ConvertTupleToStruct/IConvertTupleToStructCodeRefactoringProvider.cs
...eToStruct/IConvertTupleToStructCodeRefactoringProvider.cs
+17
-0
src/Features/Core/Portable/ConvertTupleToStruct/IRemoteConvertTupleToStructCodeRefactoringProvider.cs
...uct/IRemoteConvertTupleToStructCodeRefactoringProvider.cs
+27
-0
src/Features/Core/Portable/ConvertTupleToStruct/Scope.cs
src/Features/Core/Portable/ConvertTupleToStruct/Scope.cs
+14
-0
src/Features/VisualBasic/Portable/ConvertTupleToStruct/VisualBasicConvertTupleToStructCodeRefactoringProvider.vb
...VisualBasicConvertTupleToStructCodeRefactoringProvider.vb
+2
-7
src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs
...s/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs
+6
-0
src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs
src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs
+3
-0
src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_ConvertTupleToStruct.cs
...eHub/Services/CodeAnalysisService_ConvertTupleToStruct.cs
+86
-0
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs
...redUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs
+2
-0
src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb
...sic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb
+10
-2
未找到文件。
src/EditorFeatures/CSharpTest/ConvertTupleToStruct/ConvertTupleToStructTests.cs
浏览文件 @
3a3029d8
此差异已折叠。
点击以展开。
src/EditorFeatures/VisualBasicTest/ConvertTupleToStruct/ConvertTupleToStructTests.vb
浏览文件 @
3a3029d8
此差异已折叠。
点击以展开。
src/Features/CSharp/Portable/ConvertTupleToStruct/CSharpConvertTupleToStructCodeRefactoringProvider.cs
浏览文件 @
3a3029d8
...
...
@@ -7,10 +7,12 @@
using
Microsoft.CodeAnalysis.CodeRefactorings
;
using
Microsoft.CodeAnalysis.ConvertTupleToStruct
;
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.Host.Mef
;
namespace
Microsoft.CodeAnalysis.CSharp.ConvertTupleToStruct
{
[
ExtensionOrder
(
Before
=
PredefinedCodeRefactoringProviderNames
.
IntroduceVariable
)]
[
ExportLanguageService
(
typeof
(
IConvertTupleToStructCodeRefactoringProvider
),
LanguageNames
.
CSharp
)]
[
ExportCodeRefactoringProvider
(
LanguageNames
.
CSharp
,
Name
=
nameof
(
PredefinedCodeRefactoringProviderNames
.
ConvertTupleToStruct
)),
Shared
]
internal
class
CSharpConvertTupleToStructCodeRefactoringProvider
:
AbstractConvertTupleToStructCodeRefactoringProvider
<
...
...
@@ -30,12 +32,5 @@ internal class CSharpConvertTupleToStructCodeRefactoringProvider :
public
CSharpConvertTupleToStructCodeRefactoringProvider
()
{
}
protected
override
ObjectCreationExpressionSyntax
CreateObjectCreationExpression
(
NameSyntax
nameNode
,
SyntaxToken
openParen
,
SeparatedSyntaxList
<
ArgumentSyntax
>
arguments
,
SyntaxToken
closeParen
)
{
return
SyntaxFactory
.
ObjectCreationExpression
(
nameNode
,
SyntaxFactory
.
ArgumentList
(
openParen
,
arguments
,
closeParen
),
initializer
:
null
);
}
}
}
src/Features/Core/Portable/ConvertTupleToStruct/AbstractConvertTupleToStructCodeRefactoringProvider.cs
浏览文件 @
3a3029d8
...
...
@@ -9,6 +9,7 @@
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis
;
using
Microsoft.CodeAnalysis.CodeActions
;
using
Microsoft.CodeAnalysis.CodeGeneration
;
using
Microsoft.CodeAnalysis.CodeRefactorings
;
...
...
@@ -16,8 +17,11 @@
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.Formatting
;
using
Microsoft.CodeAnalysis.GenerateEqualsAndGetHashCodeFromMembers
;
using
Microsoft.CodeAnalysis.Host
;
using
Microsoft.CodeAnalysis.Internal.Log
;
using
Microsoft.CodeAnalysis.LanguageServices
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Remote
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Shared.Utilities
;
using
Microsoft.CodeAnalysis.Simplification
;
...
...
@@ -37,7 +41,7 @@ internal abstract partial class AbstractConvertTupleToStructCodeRefactoringProvi
TTupleTypeSyntax
,
TTypeBlockSyntax
,
TNamespaceDeclarationSyntax
>
:
CodeRefactoringProvider
:
CodeRefactoringProvider
,
IConvertTupleToStructCodeRefactoringProvider
where
TExpressionSyntax
:
SyntaxNode
where
TNameSyntax
:
TExpressionSyntax
where
TIdentifierNameSyntax
:
TNameSyntax
...
...
@@ -49,17 +53,6 @@ internal abstract partial class AbstractConvertTupleToStructCodeRefactoringProvi
where
TTypeBlockSyntax
:
SyntaxNode
where
TNamespaceDeclarationSyntax
:
SyntaxNode
{
private
enum
Scope
{
ContainingMember
,
ContainingType
,
ContainingProject
,
DependentProjects
}
protected
abstract
TObjectCreationExpressionSyntax
CreateObjectCreationExpression
(
TNameSyntax
nameNode
,
SyntaxToken
openParen
,
SeparatedSyntaxList
<
TArgumentSyntax
>
arguments
,
SyntaxToken
closeParen
);
public
override
async
Task
ComputeRefactoringsAsync
(
CodeRefactoringContext
context
)
{
var
(
document
,
textSpan
,
cancellationToken
)
=
context
;
...
...
@@ -75,15 +68,15 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
// If it does, we can't convert this. There is no way to describe this anonymous type
// in the concrete type we create.
var
fields
=
tupleType
.
TupleElements
;
var
containsAnonymousType
=
fields
.
Any
(
p
=>
p
.
Type
.
ContainsAnonymousType
());
var
containsAnonymousType
=
fields
.
Any
<
IFieldSymbol
>
(
p
=>
p
.
Type
.
ContainsAnonymousType
());
if
(
containsAnonymousType
)
{
return
;
}
var
capturedTypeParameters
=
fields
.
Select
(
p
=>
p
.
Type
)
.
SelectMany
(
t
=>
t
.
GetReferencedTypeParameters
())
fields
.
Select
<
IFieldSymbol
,
ITypeSymbol
>
(
p
=>
p
.
Type
)
.
SelectMany
<
ITypeSymbol
,
ITypeParameterSymbol
>
(
t
=>
t
.
GetReferencedTypeParameters
())
.
Distinct
()
.
ToImmutableArray
();
...
...
@@ -112,7 +105,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
//
// this means we can only find tuples like ```(x: 1, ...)``` but not ```(1, 2)```. The
// latter has members called Item1 and Item2, but those names don't show up in source.
if
(
fields
.
All
(
f
=>
f
.
CorrespondingTupleField
!=
f
))
if
(
fields
.
All
<
IFieldSymbol
>
(
f
=>
f
.
CorrespondingTupleField
!=
f
))
{
scopes
.
Add
(
CreateAction
(
context
,
Scope
.
ContainingProject
));
scopes
.
Add
(
CreateAction
(
context
,
Scope
.
DependentProjects
));
...
...
@@ -141,7 +134,7 @@ private static string GetTitle(Scope scope)
_
=>
throw
ExceptionUtilities
.
UnexpectedValue
(
scope
),
};
private
async
Task
<(
SyntaxNode
,
INamedTypeSymbol
)>
TryGetTupleInfoAsync
(
private
static
async
Task
<(
SyntaxNode
,
INamedTypeSymbol
)>
TryGetTupleInfoAsync
(
Document
document
,
TextSpan
span
,
CancellationToken
cancellationToken
)
{
// Enable refactoring either for TupleExpression or TupleType
...
...
@@ -163,7 +156,59 @@ private static string GetTitle(Scope scope)
return
(
expressionOrType
,
tupleType
);
}
private
async
Task
<
Solution
>
ConvertToStructAsync
(
public
async
Task
<
Solution
>
ConvertToStructAsync
(
Document
document
,
TextSpan
span
,
Scope
scope
,
CancellationToken
cancellationToken
)
{
cancellationToken
.
ThrowIfCancellationRequested
();
using
(
Logger
.
LogBlock
(
FunctionId
.
AbstractConvertTupleToStructCodeRefactoringProvider_ConvertToStructAsync
,
cancellationToken
))
{
var
solution
=
document
.
Project
.
Solution
;
var
client
=
await
RemoteHostClient
.
TryGetClientAsync
(
solution
.
Workspace
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
client
!=
null
)
{
var
resultOpt
=
await
client
.
TryRunRemoteAsync
<
SerializableConvertTupleToStructResult
>(
WellKnownServiceHubServices
.
CodeAnalysisService
,
nameof
(
IRemoteConvertTupleToStructCodeRefactoringProvider
.
ConvertToStructAsync
),
solution
,
new
object
[]
{
document
.
Id
,
span
,
scope
,
},
callbackTarget
:
null
,
cancellationToken
).
ConfigureAwait
(
false
);
if
(
resultOpt
.
HasValue
)
{
var
result
=
resultOpt
.
Value
;
var
resultSolution
=
await
RemoteUtilities
.
UpdateSolutionAsync
(
solution
,
result
.
DocumentTextChanges
,
cancellationToken
).
ConfigureAwait
(
false
);
return
await
AddRenameTokenAsync
(
resultSolution
,
result
.
RenamedToken
,
cancellationToken
).
ConfigureAwait
(
false
);
}
}
}
return
await
ConvertToStructInCurrentProcessAsync
(
document
,
span
,
scope
,
cancellationToken
).
ConfigureAwait
(
false
);
}
private
async
Task
<
Solution
>
AddRenameTokenAsync
(
Solution
solution
,
(
DocumentId
documentId
,
TextSpan
span
)
renamedToken
,
CancellationToken
cancellationToken
)
{
var
document
=
solution
.
GetDocument
(
renamedToken
.
documentId
);
var
root
=
await
document
.
GetSyntaxRootAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
token
=
root
.
FindToken
(
renamedToken
.
span
.
Start
);
var
newRoot
=
root
.
ReplaceToken
(
token
,
token
.
WithAdditionalAnnotations
(
RenameAnnotation
.
Create
()));
return
document
.
WithSyntaxRoot
(
newRoot
).
Project
.
Solution
;
}
private
static
async
Task
<
Solution
>
ConvertToStructInCurrentProcessAsync
(
Document
document
,
TextSpan
span
,
Scope
scope
,
CancellationToken
cancellationToken
)
{
var
(
tupleExprOrTypeNode
,
tupleType
)
=
await
TryGetTupleInfoAsync
(
...
...
@@ -187,8 +232,8 @@ private static string GetTitle(Scope scope)
"NewStruct"
,
n
=>
semanticModel
.
LookupSymbols
(
position
,
name
:
n
).
IsEmpty
);
var
capturedTypeParameters
=
tupleType
.
TupleElements
.
Select
(
p
=>
p
.
Type
)
.
SelectMany
(
t
=>
t
.
GetReferencedTypeParameters
())
tupleType
.
TupleElements
.
Select
<
IFieldSymbol
,
ITypeSymbol
>
(
p
=>
p
.
Type
)
.
SelectMany
<
ITypeSymbol
,
ITypeParameterSymbol
>
(
t
=>
t
.
GetReferencedTypeParameters
())
.
Distinct
()
.
ToImmutableArray
();
...
...
@@ -219,7 +264,7 @@ private static string GetTitle(Scope scope)
return
updatedSolution
;
}
private
async
Task
ReplaceExpressionAndTypesInScopeAsync
(
private
static
async
Task
ReplaceExpressionAndTypesInScopeAsync
(
Dictionary
<
Document
,
SyntaxEditor
>
documentToEditorMap
,
ImmutableArray
<
DocumentToUpdate
>
documentsToUpdate
,
SyntaxNode
tupleExprOrTypeNode
,
INamedTypeSymbol
tupleType
,
...
...
@@ -355,12 +400,12 @@ private static string GetTitle(Scope scope)
// starting project.
var
dependentProjects
=
graph
.
GetProjectsThatDirectlyDependOnThisProject
(
startingProject
.
Id
);
var
allProjects
=
dependentProjects
.
Select
(
solution
.
GetProject
)
var
allProjects
=
dependentProjects
.
Select
<
ProjectId
,
Project
>
(
solution
.
GetProject
)
.
Where
(
p
=>
p
.
SupportsCompilation
)
.
Concat
(
startingProject
).
ToSet
();
var
result
=
ArrayBuilder
<
DocumentToUpdate
>.
GetInstance
();
var
tupleFieldNames
=
tupleType
.
TupleElements
.
SelectAsArray
(
f
=>
f
.
Name
);
var
tupleFieldNames
=
tupleType
.
TupleElements
.
SelectAsArray
<
IFieldSymbol
,
string
>
(
f
=>
f
.
Name
);
foreach
(
var
project
in
allProjects
)
{
...
...
@@ -375,7 +420,7 @@ private static string GetTitle(Scope scope)
Project
project
,
INamedTypeSymbol
tupleType
,
CancellationToken
cancellationToken
)
{
var
result
=
ArrayBuilder
<
DocumentToUpdate
>.
GetInstance
();
var
tupleFieldNames
=
tupleType
.
TupleElements
.
SelectAsArray
(
f
=>
f
.
Name
);
var
tupleFieldNames
=
tupleType
.
TupleElements
.
SelectAsArray
<
IFieldSymbol
,
string
>
(
f
=>
f
.
Name
);
await
AddDocumentsToUpdateForProjectAsync
(
project
,
result
,
tupleFieldNames
,
cancellationToken
).
ConfigureAwait
(
false
);
...
...
@@ -427,7 +472,7 @@ private static bool InfoProbablyContainsTupleFieldNames(SyntaxTreeIndex info, Im
foreach
(
var
group
in
declarationService
.
GetDeclarations
(
typeSymbol
).
GroupBy
(
r
=>
r
.
SyntaxTree
))
{
var
document
=
solution
.
GetDocument
(
group
.
Key
);
var
nodes
=
group
.
SelectAsArray
(
r
=>
r
.
GetSyntax
(
cancellationToken
));
var
nodes
=
group
.
SelectAsArray
<
SyntaxReference
,
SyntaxNode
>
(
r
=>
r
.
GetSyntax
(
cancellationToken
));
result
.
Add
(
new
DocumentToUpdate
(
document
,
nodes
));
}
...
...
@@ -506,7 +551,7 @@ private static bool InfoProbablyContainsTupleFieldNames(SyntaxTreeIndex info, Im
return
currentSolution
;
}
private
async
Task
<
bool
>
ReplaceTupleExpressionsAndTypesInDocumentAsync
(
private
static
async
Task
<
bool
>
ReplaceTupleExpressionsAndTypesInDocumentAsync
(
Document
document
,
SyntaxEditor
editor
,
SyntaxNode
startingNode
,
INamedTypeSymbol
tupleType
,
TNameSyntax
fullyQualifiedStructName
,
string
structName
,
ImmutableArray
<
ITypeParameterSymbol
>
typeParameters
,
...
...
@@ -526,7 +571,7 @@ private static bool InfoProbablyContainsTupleFieldNames(SyntaxTreeIndex info, Im
return
changed
;
}
private
async
Task
<
bool
>
ReplaceMatchingTupleExpressionsAsync
(
private
static
async
Task
<
bool
>
ReplaceMatchingTupleExpressionsAsync
(
Document
document
,
SyntaxEditor
editor
,
SyntaxNode
startingNode
,
INamedTypeSymbol
tupleType
,
TNameSyntax
qualifiedTypeName
,
string
typeName
,
ImmutableArray
<
ITypeParameterSymbol
>
typeParameters
,
...
...
@@ -552,8 +597,7 @@ private static bool InfoProbablyContainsTupleFieldNames(SyntaxTreeIndex info, Im
{
changed
=
true
;
ReplaceWithObjectCreation
(
syntaxFacts
,
editor
,
typeName
,
typeParameters
,
qualifiedTypeName
,
startingNode
,
childCreation
);
editor
,
typeName
,
typeParameters
,
qualifiedTypeName
,
startingNode
,
childCreation
);
}
}
...
...
@@ -583,8 +627,8 @@ private static bool AreEquivalent(StringComparer comparer, INamedTypeSymbol tupl
return
true
;
}
private
void
ReplaceWithObjectCreation
(
ISyntaxFactsService
syntaxFacts
,
SyntaxEditor
editor
,
string
typeName
,
ImmutableArray
<
ITypeParameterSymbol
>
typeParameters
,
private
static
void
ReplaceWithObjectCreation
(
SyntaxEditor
editor
,
string
typeName
,
ImmutableArray
<
ITypeParameterSymbol
>
typeParameters
,
TNameSyntax
qualifiedTypeName
,
SyntaxNode
startingCreationNode
,
TTupleExpressionSyntax
childCreation
)
{
// Use the callback form as tuples types may be nested, and we want to
...
...
@@ -600,33 +644,34 @@ private static bool AreEquivalent(StringComparer comparer, INamedTypeSymbol tupl
?
CreateStructNameNode
(
g
,
typeName
,
typeParameters
,
addRenameAnnotation
:
true
)
:
qualifiedTypeName
;
var
syntaxFacts
=
g
.
SyntaxFacts
;
syntaxFacts
.
GetPartsOfTupleExpression
<
TArgumentSyntax
>(
currentTupleExpr
,
out
var
openParen
,
out
var
arguments
,
out
var
closeParen
);
arguments
=
ConvertArguments
(
syntaxFacts
,
g
,
arguments
);
arguments
=
ConvertArguments
(
g
,
arguments
);
return
Create
ObjectCreationExpression
(
typeNameNode
,
openParen
,
arguments
,
closeParen
)
return
g
.
ObjectCreationExpression
(
typeNameNode
,
openParen
,
arguments
,
closeParen
)
.
WithAdditionalAnnotations
(
Formatter
.
Annotation
);
});
}
private
SeparatedSyntaxList
<
TArgumentSyntax
>
ConvertArguments
(
ISyntaxFactsService
syntaxFacts
,
SyntaxGenerator
generator
,
SeparatedSyntaxList
<
TArgumentSyntax
>
arguments
)
=>
generator
.
SeparatedList
<
TArgumentSyntax
>(
ConvertArguments
(
syntaxFacts
,
generator
,
arguments
.
GetWithSeparators
()));
private
static
SeparatedSyntaxList
<
TArgumentSyntax
>
ConvertArguments
(
SyntaxGenerator
generator
,
SeparatedSyntaxList
<
TArgumentSyntax
>
arguments
)
=>
generator
.
SeparatedList
<
TArgumentSyntax
>(
ConvertArguments
(
generator
,
arguments
.
GetWithSeparators
()));
private
SyntaxNodeOrTokenList
ConvertArguments
(
ISyntaxFactsService
syntaxFacts
,
SyntaxGenerator
generator
,
SyntaxNodeOrTokenList
list
)
=>
new
SyntaxNodeOrTokenList
(
list
.
Select
(
v
=>
ConvertArgumentOrToken
(
syntaxFacts
,
generator
,
v
)));
private
static
SyntaxNodeOrTokenList
ConvertArguments
(
SyntaxGenerator
generator
,
SyntaxNodeOrTokenList
list
)
=>
new
SyntaxNodeOrTokenList
(
list
.
Select
(
v
=>
ConvertArgumentOrToken
(
generator
,
v
)));
private
SyntaxNodeOrToken
ConvertArgumentOrToken
(
ISyntaxFactsService
syntaxFacts
,
SyntaxGenerator
generator
,
SyntaxNodeOrToken
arg
)
private
static
SyntaxNodeOrToken
ConvertArgumentOrToken
(
SyntaxGenerator
generator
,
SyntaxNodeOrToken
arg
)
=>
arg
.
IsToken
?
arg
:
ConvertArgument
(
syntaxFacts
,
generator
,
(
TArgumentSyntax
)
arg
.
AsNode
());
:
ConvertArgument
(
generator
,
(
TArgumentSyntax
)
arg
.
AsNode
());
private
TArgumentSyntax
ConvertArgument
(
ISyntaxFactsService
syntaxFacts
,
SyntaxGenerator
generator
,
TArgumentSyntax
argument
)
private
static
TArgumentSyntax
ConvertArgument
(
SyntaxGenerator
generator
,
TArgumentSyntax
argument
)
{
// Keep named arguments for literal args. It helps keep the code self-documenting.
// Remove for complex args as it's most likely just clutter a person doesn't need
// when instantiating their new type.
var
expr
=
s
yntaxFacts
.
GetExpressionOfArgument
(
argument
);
var
expr
=
generator
.
S
yntaxFacts
.
GetExpressionOfArgument
(
argument
);
if
(
expr
is
TLiteralExpressionSyntax
)
{
return
argument
;
...
...
@@ -635,7 +680,7 @@ private SyntaxNodeOrToken ConvertArgumentOrToken(ISyntaxFactsService syntaxFacts
return
(
TArgumentSyntax
)
generator
.
Argument
(
expr
).
WithTriviaFrom
(
argument
);
}
private
async
Task
<
bool
>
ReplaceMatchingTupleTypesAsync
(
private
static
async
Task
<
bool
>
ReplaceMatchingTupleTypesAsync
(
Document
document
,
SyntaxEditor
editor
,
SyntaxNode
startingNode
,
INamedTypeSymbol
tupleType
,
TNameSyntax
qualifiedTypeName
,
string
typeName
,
ImmutableArray
<
ITypeParameterSymbol
>
typeParameters
,
...
...
@@ -667,7 +712,7 @@ private SyntaxNodeOrToken ConvertArgumentOrToken(ISyntaxFactsService syntaxFacts
return
changed
;
}
private
void
ReplaceWithTypeNode
(
private
static
void
ReplaceWithTypeNode
(
SyntaxEditor
editor
,
string
typeName
,
ImmutableArray
<
ITypeParameterSymbol
>
typeParameters
,
TNameSyntax
qualifiedTypeName
,
SyntaxNode
startingNode
,
TTupleTypeSyntax
childTupleType
)
{
...
...
@@ -751,7 +796,7 @@ private SyntaxNodeOrToken ConvertArgumentOrToken(ISyntaxFactsService syntaxFacts
explicitInterfaceImplementations
:
default
,
WellKnownMemberNames
.
DeconstructMethodName
,
typeParameters
:
default
,
constructor
.
Parameters
.
SelectAsArray
(
p
=>
constructor
.
Parameters
.
SelectAsArray
<
IParameterSymbol
,
IParameterSymbol
>
(
p
=>
CodeGenerationSymbolFactory
.
CreateParameterSymbol
(
RefKind
.
Out
,
p
.
Type
,
p
.
Name
)),
assignments
);
}
...
...
@@ -763,7 +808,7 @@ private SyntaxNodeOrToken ConvertArgumentOrToken(ISyntaxFactsService syntaxFacts
const
string
valueName
=
"value"
;
var
valueNode
=
generator
.
IdentifierName
(
valueName
);
var
arguments
=
tupleType
.
TupleElements
.
SelectAsArray
(
var
arguments
=
tupleType
.
TupleElements
.
SelectAsArray
<
IFieldSymbol
,
SyntaxNode
>
(
field
=>
generator
.
Argument
(
generator
.
MemberAccessExpression
(
valueNode
,
field
.
Name
)));
...
...
@@ -810,7 +855,7 @@ private SyntaxNodeOrToken ConvertArgumentOrToken(ISyntaxFactsService syntaxFacts
// For every property, create a corresponding parameter, as well as an assignment
// statement from that parameter to the property.
var
parameterToPropMap
=
new
Dictionary
<
string
,
ISymbol
>();
var
parameters
=
fields
.
SelectAsArray
(
field
=>
var
parameters
=
fields
.
SelectAsArray
<
IFieldSymbol
,
IParameterSymbol
>
(
field
=>
{
var
parameter
=
CodeGenerationSymbolFactory
.
CreateParameterSymbol
(
field
.
Type
,
field
.
Name
.
ToCamelCase
(
trimLeadingTypePrefix
:
false
));
...
...
src/Features/Core/Portable/ConvertTupleToStruct/IConvertTupleToStructCodeRefactoringProvider.cs
0 → 100644
浏览文件 @
3a3029d8
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.Host
;
using
Microsoft.CodeAnalysis.Text
;
namespace
Microsoft.CodeAnalysis.ConvertTupleToStruct
{
internal
interface
IConvertTupleToStructCodeRefactoringProvider
:
ILanguageService
{
Task
<
Solution
>
ConvertToStructAsync
(
Document
document
,
TextSpan
span
,
Scope
scope
,
CancellationToken
cancellationToken
);
}
}
src/Features/Core/Portable/ConvertTupleToStruct/IRemoteConvertTupleToStructCodeRefactoringProvider.cs
0 → 100644
浏览文件 @
3a3029d8
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.Remote
;
using
Microsoft.CodeAnalysis.Text
;
namespace
Microsoft.CodeAnalysis.ConvertTupleToStruct
{
internal
interface
IRemoteConvertTupleToStructCodeRefactoringProvider
{
Task
<
SerializableConvertTupleToStructResult
>
ConvertToStructAsync
(
PinnedSolutionInfo
solutionInfo
,
DocumentId
documentId
,
TextSpan
span
,
Scope
scope
,
CancellationToken
cancellationToken
);
}
internal
class
SerializableConvertTupleToStructResult
{
public
(
DocumentId
,
TextChange
[])[]
DocumentTextChanges
;
public
(
DocumentId
,
TextSpan
)
RenamedToken
;
}
}
src/Features/Core/Portable/ConvertTupleToStruct/Scope.cs
0 → 100644
浏览文件 @
3a3029d8
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace
Microsoft.CodeAnalysis.ConvertTupleToStruct
{
internal
enum
Scope
{
ContainingMember
,
ContainingType
,
ContainingProject
,
DependentProjects
}
}
src/Features/VisualBasic/Portable/ConvertTupleToStruct/VisualBasicConvertTupleToStructCodeRefactoringProvider.vb
浏览文件 @
3a3029d8
...
...
@@ -6,10 +6,12 @@ Imports System.Composition
Imports
System.Diagnostics.CodeAnalysis
Imports
Microsoft.CodeAnalysis.CodeRefactorings
Imports
Microsoft.CodeAnalysis.ConvertTupleToStruct
Imports
Microsoft.CodeAnalysis.Host.Mef
Imports
Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace
Microsoft.CodeAnalysis.VisualBasic.ConvertTupleToStruct
<
ExtensionOrder
(
Before
:
=
PredefinedCodeRefactoringProviderNames
.
IntroduceVariable
)
>
<
ExportLanguageService
(
GetType
(
IConvertTupleToStructCodeRefactoringProvider
),
LanguageNames
.
VisualBasic
)
>
<
ExportCodeRefactoringProvider
(
LanguageNames
.
VisualBasic
,
Name
:
=
PredefinedCodeRefactoringProviderNames
.
ConvertTupleToStruct
),
[
Shared
]
>
Friend
Class
VisualBasicConvertTupleToStructCodeRefactoringProvider
Inherits
AbstractConvertTupleToStructCodeRefactoringProvider
(
Of
...
...
@@ -28,12 +30,5 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ConvertTupleToStruct
<
SuppressMessage
(
"RoslynDiagnosticsReliability"
,
"RS0033:Importing constructor should be [Obsolete]"
,
Justification
:
=
"Used in test code: https://github.com/dotnet/roslyn/issues/42814"
)
>
Public
Sub
New
()
End
Sub
Protected
Overrides
Function
CreateObjectCreationExpression
(
nameNode
As
NameSyntax
,
openParen
As
SyntaxToken
,
arguments
As
SeparatedSyntaxList
(
Of
ArgumentSyntax
),
closeParen
As
SyntaxToken
)
As
ObjectCreationExpressionSyntax
Return
SyntaxFactory
.
ObjectCreationExpression
(
attributeLists
:
=
Nothing
,
nameNode
,
SyntaxFactory
.
ArgumentList
(
openParen
,
arguments
,
closeParen
),
initializer
:
=
Nothing
)
End
Function
End
Class
End
Namespace
src/Workspaces/CSharp/Portable/CodeGeneration/CSharpSyntaxGenerator.cs
浏览文件 @
3a3029d8
...
...
@@ -3092,6 +3092,12 @@ public override SyntaxNode ArrayCreationExpression(SyntaxNode elementType, IEnum
public
override
SyntaxNode
ObjectCreationExpression
(
SyntaxNode
type
,
IEnumerable
<
SyntaxNode
>
arguments
)
=>
SyntaxFactory
.
ObjectCreationExpression
((
TypeSyntax
)
type
,
CreateArgumentList
(
arguments
),
null
);
internal
override
SyntaxNode
ObjectCreationExpression
(
SyntaxNode
type
,
SyntaxToken
openParen
,
SeparatedSyntaxList
<
SyntaxNode
>
arguments
,
SyntaxToken
closeParen
)
=>
SyntaxFactory
.
ObjectCreationExpression
(
(
TypeSyntax
)
type
,
SyntaxFactory
.
ArgumentList
(
openParen
,
arguments
,
closeParen
),
initializer
:
null
);
private
static
ArgumentListSyntax
CreateArgumentList
(
IEnumerable
<
SyntaxNode
>
arguments
)
=>
SyntaxFactory
.
ArgumentList
(
CreateArguments
(
arguments
));
...
...
src/Workspaces/Core/Portable/Editing/SyntaxGenerator.cs
浏览文件 @
3a3029d8
...
...
@@ -1960,6 +1960,9 @@ public SyntaxNode MemberAccessExpression(SyntaxNode expression, string memberNam
/// </summary>
public
abstract
SyntaxNode
ObjectCreationExpression
(
SyntaxNode
namedType
,
IEnumerable
<
SyntaxNode
>
arguments
);
internal
abstract
SyntaxNode
ObjectCreationExpression
(
SyntaxNode
namedType
,
SyntaxToken
openParen
,
SeparatedSyntaxList
<
SyntaxNode
>
arguments
,
SyntaxToken
closeParen
);
/// <summary>
/// Creates an object creation expression.
/// </summary>
...
...
src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_ConvertTupleToStruct.cs
0 → 100644
浏览文件 @
3a3029d8
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.CodeActions
;
using
Microsoft.CodeAnalysis.ConvertTupleToStruct
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Text
;
using
Roslyn.Utilities
;
namespace
Microsoft.CodeAnalysis.Remote
{
// root level service for all Roslyn services
internal
partial
class
CodeAnalysisService
:
IRemoteConvertTupleToStructCodeRefactoringProvider
{
public
Task
<
SerializableConvertTupleToStructResult
>
ConvertToStructAsync
(
PinnedSolutionInfo
solutionInfo
,
DocumentId
documentId
,
TextSpan
span
,
Scope
scope
,
CancellationToken
cancellationToken
)
{
return
RunServiceAsync
<
SerializableConvertTupleToStructResult
>(
async
()
=>
{
using
(
UserOperationBooster
.
Boost
())
{
var
solution
=
await
GetSolutionAsync
(
solutionInfo
,
cancellationToken
).
ConfigureAwait
(
false
);
var
document
=
solution
.
GetDocument
(
documentId
);
var
service
=
document
.
GetLanguageService
<
IConvertTupleToStructCodeRefactoringProvider
>();
var
updatedSolution
=
await
service
.
ConvertToStructAsync
(
document
,
span
,
scope
,
cancellationToken
).
ConfigureAwait
(
false
);
var
cleanedSolution
=
await
CleanupAsync
(
solution
,
updatedSolution
,
cancellationToken
).
ConfigureAwait
(
false
);
var
documentTextChanges
=
await
RemoteUtilities
.
GetDocumentTextChangesAsync
(
solution
,
cleanedSolution
,
cancellationToken
).
ConfigureAwait
(
false
);
var
renamedToken
=
await
GetRenamedTokenAsync
(
solution
,
cleanedSolution
,
cancellationToken
).
ConfigureAwait
(
false
);
return
new
SerializableConvertTupleToStructResult
{
DocumentTextChanges
=
documentTextChanges
,
RenamedToken
=
renamedToken
,
};
}
},
cancellationToken
);
}
private
async
Task
<(
DocumentId
,
TextSpan
)>
GetRenamedTokenAsync
(
Solution
oldSolution
,
Solution
newSolution
,
CancellationToken
cancellationToken
)
{
var
changes
=
newSolution
.
GetChangedDocuments
(
oldSolution
);
foreach
(
var
docId
in
changes
)
{
var
document
=
newSolution
.
GetDocument
(
docId
);
var
root
=
await
document
.
GetSyntaxRootAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
renamedToken
=
root
.
GetAnnotatedTokens
(
RenameAnnotation
.
Kind
).
FirstOrNull
();
if
(
renamedToken
==
null
)
continue
;
return
(
docId
,
renamedToken
.
Value
.
Span
);
}
throw
ExceptionUtilities
.
Unreachable
;
}
private
async
Task
<
Solution
>
CleanupAsync
(
Solution
oldSolution
,
Solution
newSolution
,
CancellationToken
cancellationToken
)
{
var
changes
=
newSolution
.
GetChangedDocuments
(
oldSolution
);
var
final
=
newSolution
;
foreach
(
var
docId
in
changes
)
{
var
cleaned
=
await
CodeAction
.
CleanupDocumentAsync
(
newSolution
.
GetDocument
(
docId
),
cancellationToken
).
ConfigureAwait
(
false
);
var
cleanedRoot
=
await
cleaned
.
GetSyntaxRootAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
final
=
final
.
WithDocumentSyntaxRoot
(
docId
,
cleanedRoot
);
}
return
final
;
}
}
}
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Log/FunctionId.cs
浏览文件 @
3a3029d8
...
...
@@ -487,5 +487,7 @@ internal enum FunctionId
ChangeSignature_Data
=
389
,
AbstractEncapsulateFieldService_EncapsulateFieldsAsync
=
390
,
AbstractConvertTupleToStructCodeRefactoringProvider_ConvertToStructAsync
=
400
,
}
}
src/Workspaces/VisualBasic/Portable/CodeGeneration/VisualBasicSyntaxGenerator.vb
浏览文件 @
3a3029d8
...
...
@@ -352,10 +352,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Public
Overloads
Overrides
Function
ObjectCreationExpression
(
typeName
As
SyntaxNode
,
arguments
As
IEnumerable
(
Of
SyntaxNode
))
As
SyntaxNode
Return
SyntaxFactory
.
ObjectCreationExpression
(
Nothing
,
attributeLists
:
=
Nothing
,
DirectCast
(
typeName
,
TypeSyntax
),
CreateArgumentList
(
arguments
),
Nothing
)
initializer
:
=
Nothing
)
End
Function
Friend
Overrides
Function
ObjectCreationExpression
(
typeName
As
SyntaxNode
,
openParen
As
SyntaxToken
,
arguments
As
SeparatedSyntaxList
(
Of
SyntaxNode
),
closeParen
As
SyntaxToken
)
As
SyntaxNode
Return
SyntaxFactory
.
ObjectCreationExpression
(
attributeLists
:
=
Nothing
,
DirectCast
(
typeName
,
TypeSyntax
),
SyntaxFactory
.
ArgumentList
(
openParen
,
arguments
,
closeParen
),
initializer
:
=
Nothing
)
End
Function
Public
Overrides
Function
QualifiedName
(
left
As
SyntaxNode
,
right
As
SyntaxNode
)
As
SyntaxNode
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录