未验证 提交 569124ee 编写于 作者: J Julien Couvreur 提交者: GitHub

Merge pull request #28257 from CyrusNajmabadi/convertTupleToStruct

Add feature to allow converting from a tuple to a named-struct.
......@@ -656,8 +656,24 @@ private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActi
foreach (var action in refactoring.Actions)
{
refactoringSuggestedActions.Add(new CodeRefactoringSuggestedAction(
_owner, workspace, _subjectBuffer, refactoring.Provider, action));
if (action.NestedCodeActions.Length > 0)
{
var nestedActions = action.NestedCodeActions.SelectAsArray(
na => new CodeRefactoringSuggestedAction(
_owner, workspace, _subjectBuffer, refactoring.Provider, na));
var set = new SuggestedActionSet(categoryName: null,
actions: nestedActions, priority: SuggestedActionSetPriority.Medium, applicableToSpan: applicableSpan);
refactoringSuggestedActions.Add(new SuggestedActionWithNestedActions(
_owner, workspace, _subjectBuffer,
refactoring.Provider, action, set));
}
else
{
refactoringSuggestedActions.Add(new CodeRefactoringSuggestedAction(
_owner, workspace, _subjectBuffer, refactoring.Provider, action));
}
}
return new SuggestedActionSet(
......
......@@ -487,7 +487,16 @@ private static async Task VerifyAgainstWorkspaceDefinitionAsync(string expectedT
var root = await doc.GetSyntaxRootAsync();
var expectedDocument = expectedProject.Documents.Single(d => d.Name == doc.Name);
var expectedRoot = await expectedDocument.GetSyntaxRootAsync();
Assert.Equal(expectedRoot.ToFullString(), root.ToFullString());
var expected = expectedRoot.ToFullString();
if (expected == "")
{
Assert.Equal((object)expected, root.ToFullString());
}
else
{
Assert.Equal(expected, root.ToFullString());
}
}
}
}
......
......@@ -35,6 +35,7 @@ public abstract class AbstractCodeActionTest : AbstractCodeActionOrUserDiagnosti
var actions = refactoring == null
? ImmutableArray<CodeAction>.Empty
: refactoring.Actions;
actions = MassageActions(actions);
return (actions, actions.IsDefaultOrEmpty ? null : actions[parameters.index]);
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Composition;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.ConvertTupleToStruct;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.ConvertTupleToStruct
{
[ExtensionOrder(Before = PredefinedCodeRefactoringProviderNames.IntroduceVariable)]
[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = nameof(PredefinedCodeRefactoringProviderNames.ConvertTupleToStruct)), Shared]
internal class CSharpConvertTupleToStructCodeRefactoringProvider :
AbstractConvertTupleToStructCodeRefactoringProvider<
ExpressionSyntax,
NameSyntax,
IdentifierNameSyntax,
LiteralExpressionSyntax,
ObjectCreationExpressionSyntax,
TupleExpressionSyntax,
ArgumentSyntax,
TupleTypeSyntax,
TypeDeclarationSyntax,
NamespaceDeclarationSyntax>
{
protected override ObjectCreationExpressionSyntax CreateObjectCreationExpression(
NameSyntax nameNode, SyntaxToken openParen, SeparatedSyntaxList<ArgumentSyntax> arguments, SyntaxToken closeParen)
{
return SyntaxFactory.ObjectCreationExpression(
nameNode, SyntaxFactory.ArgumentList(openParen, arguments, closeParen), initializer: default);
}
}
}
......@@ -7,6 +7,7 @@
namespace Microsoft.CodeAnalysis.CodeRefactorings.IntroduceVariable
{
[ExtensionOrder(After = PredefinedCodeRefactoringProviderNames.ConvertTupleToStruct)]
[ExtensionOrder(After = PredefinedCodeRefactoringProviderNames.ConvertAnonymousTypeToClass)]
[ExportCodeRefactoringProvider(LanguageNames.CSharp, LanguageNames.VisualBasic,
Name = PredefinedCodeRefactoringProviderNames.IntroduceVariable), Shared]
......
......@@ -8,6 +8,7 @@ internal static class PredefinedCodeRefactoringProviderNames
public const string AddConstructorParametersFromMembers = "Add Parameters From Members Code Action Provider";
public const string ChangeSignature = "Change Signature Code Action Provider";
public const string ConvertAnonymousTypeToClass = "Convert Anonymous Type to Class Code Action Provider";
public const string ConvertTupleToStruct = "Convert Tuple to Struct Code Action Provider";
public const string EncapsulateField = "Encapsulate Field";
public const string ExtractInterface = "Extract Interface Code Action Provider";
public const string ExtractMethod = "Extract Method Code Action Provider";
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
namespace Microsoft.CodeAnalysis.ConvertTupleToStruct
{
internal struct DocumentToUpdate
{
/// <summary>
/// The document to update.
/// </summary>
public readonly Document Document;
/// <summary>
/// The subnodes in this document to walk and update. If empty, the entire document
/// should be walked.
/// </summary>
public readonly ImmutableArray<SyntaxNode> NodesToUpdate;
public DocumentToUpdate(Document document, ImmutableArray<SyntaxNode> nodesToUpdate)
{
Document = document;
NodesToUpdate = nodesToUpdate;
}
}
}
......@@ -933,6 +933,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Convert to struct.
/// </summary>
internal static string Convert_to_struct {
get {
return ResourceManager.GetString("Convert_to_struct", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Convert to tuple.
/// </summary>
......@@ -3526,6 +3535,42 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to updating usages in containing member.
/// </summary>
internal static string updating_usages_in_containing_member {
get {
return ResourceManager.GetString("updating_usages_in_containing_member", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to updating usages in containing project.
/// </summary>
internal static string updating_usages_in_containing_project {
get {
return ResourceManager.GetString("updating_usages_in_containing_project", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to updating usages in containing type.
/// </summary>
internal static string updating_usages_in_containing_type {
get {
return ResourceManager.GetString("updating_usages_in_containing_type", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to updating usages in dependent projects.
/// </summary>
internal static string updating_usages_in_dependent_projects {
get {
return ResourceManager.GetString("updating_usages_in_dependent_projects", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use {0}.
/// </summary>
......
......@@ -1382,4 +1382,19 @@ This version used in: {2}</value>
<data name="Convert_to_class" xml:space="preserve">
<value>Convert to class</value>
</data>
<data name="Convert_to_struct" xml:space="preserve">
<value>Convert to struct</value>
</data>
<data name="updating_usages_in_containing_member" xml:space="preserve">
<value>updating usages in containing member</value>
</data>
<data name="updating_usages_in_containing_project" xml:space="preserve">
<value>updating usages in containing project</value>
</data>
<data name="updating_usages_in_containing_type" xml:space="preserve">
<value>updating usages in containing type</value>
</data>
<data name="updating_usages_in_dependent_projects" xml:space="preserve">
<value>updating usages in dependent projects</value>
</data>
</root>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ Tato verze se používá zde: {2}.</target>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ Diese Version wird verwendet in: {2}</target>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ Esta versión se utiliza en: {2}</target>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ Version utilisée dans : {2}</target>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ Questa versione è usata {2}</target>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ This version used in: {2}</source>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ This version used in: {2}</source>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ Ta wersja jest używana wersja: {2}</target>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ Essa versão é usada no: {2}</target>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ This version used in: {2}</source>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ Bu sürüm şurada kullanılır: {2}</target>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ This version used in: {2}</source>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -32,6 +32,11 @@
<target state="new">Convert to class</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_struct">
<source>Convert to struct</source>
<target state="new">Convert to struct</target>
<note />
</trans-unit>
<trans-unit id="Convert_to_tuple">
<source>Convert to tuple</source>
<target state="new">Convert to tuple</target>
......@@ -2065,6 +2070,26 @@ This version used in: {2}</source>
<target state="new">Convert to conditional expression</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_member">
<source>updating usages in containing member</source>
<target state="new">updating usages in containing member</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_project">
<source>updating usages in containing project</source>
<target state="new">updating usages in containing project</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_containing_type">
<source>updating usages in containing type</source>
<target state="new">updating usages in containing type</target>
<note />
</trans-unit>
<trans-unit id="updating_usages_in_dependent_projects">
<source>updating usages in dependent projects</source>
<target state="new">updating usages in dependent projects</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Composition
Imports Microsoft.CodeAnalysis.CodeRefactorings
Imports Microsoft.CodeAnalysis.ConvertTupleToStruct
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.ConvertTupleToStruct
<ExtensionOrder(Before:=PredefinedCodeRefactoringProviderNames.IntroduceVariable)>
<ExportCodeRefactoringProvider(LanguageNames.VisualBasic, Name:=PredefinedCodeRefactoringProviderNames.ConvertTupleToStruct), [Shared]>
Friend Class VisualBasicConvertTupleToStructCodeRefactoringProvider
Inherits AbstractConvertTupleToStructCodeRefactoringProvider(Of
ExpressionSyntax,
NameSyntax,
IdentifierNameSyntax,
LiteralExpressionSyntax,
ObjectCreationExpressionSyntax,
TupleExpressionSyntax,
ArgumentSyntax,
TupleTypeSyntax,
TypeBlockSyntax,
NamespaceBlockSyntax)
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
......@@ -56,6 +56,7 @@ public static class Features
public const string CodeActionsConvertForToForEach = "CodeActions.ConvertForToForEach";
public const string CodeActionsConvertForEachToFor = "CodeActions.ConvertForEachToFor";
public const string CodeActionsConvertIfToSwitch = "CodeActions.ConvertIfToSwitch";
public const string CodeActionsConvertTupleToStruct = "CodeActions.ConvertTupleToStruct";
public const string CodeActionsConvertQueryToForEach = "CodeActions.ConvertQueryToForEach";
public const string CodeActionsCorrectExitContinue = "CodeActions.CorrectExitContinue";
public const string CodeActionsCorrectFunctionReturnType = "CodeActions.CorrectFunctionReturnType";
......
......@@ -27,6 +27,9 @@ internal class CSharpSyntaxGenerator : SyntaxGenerator
internal override SyntaxTrivia EndOfLine(string text)
=> SyntaxFactory.EndOfLine(text);
internal override SeparatedSyntaxList<TElement> SeparatedList<TElement>(SyntaxNodeOrTokenList list)
=> SyntaxFactory.SeparatedList<TElement>(list);
public static readonly SyntaxGenerator Instance = new CSharpSyntaxGenerator();
#region Declarations
......@@ -3967,9 +3970,12 @@ public override SyntaxNode WithTypeArguments(SyntaxNode expression, IEnumerable<
}
public override SyntaxNode QualifiedName(SyntaxNode left, SyntaxNode right)
{
return SyntaxFactory.QualifiedName((NameSyntax)left, (SimpleNameSyntax)right).WithAdditionalAnnotations(Simplifier.Annotation);
}
=> SyntaxFactory.QualifiedName((NameSyntax)left, (SimpleNameSyntax)right).WithAdditionalAnnotations(Simplifier.Annotation);
internal override SyntaxNode GlobalAliasedName(SyntaxNode name)
=> SyntaxFactory.AliasQualifiedName(
SyntaxFactory.IdentifierName(SyntaxFactory.Token(SyntaxKind.GlobalKeyword)),
(SimpleNameSyntax)name);
public override SyntaxNode NameExpression(INamespaceOrTypeSymbol namespaceOrTypeSymbol)
=> namespaceOrTypeSymbol.GenerateNameSyntax();
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServices;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
{
[ExportLanguageService(typeof(ISymbolDeclarationService), LanguageNames.CSharp), Shared]
internal class CSharpSymbolDeclarationService : ISymbolDeclarationService
{
public IEnumerable<SyntaxReference> GetDeclarations(ISymbol symbol)
{
return symbol != null
? symbol.DeclaringSyntaxReferences.AsEnumerable()
: SpecializedCollections.EmptyEnumerable<SyntaxReference>();
}
public ImmutableArray<SyntaxReference> GetDeclarations(ISymbol symbol)
=> symbol != null
? symbol.DeclaringSyntaxReferences
: ImmutableArray<SyntaxReference>.Empty;
}
}
......@@ -1662,6 +1662,15 @@ public bool IsTupleExpression(SyntaxNode node)
public bool IsTupleType(SyntaxNode node)
=> node.Kind() == SyntaxKind.TupleType;
public void GetPartsOfTupleExpression<TArgumentSyntax>(SyntaxNode node,
out SyntaxToken openParen, out SeparatedSyntaxList<TArgumentSyntax> arguments, out SyntaxToken closeParen) where TArgumentSyntax : SyntaxNode
{
var tupleExpression = (TupleExpressionSyntax)node;
openParen = tupleExpression.OpenParenToken;
arguments = (SeparatedSyntaxList<TArgumentSyntax>)(SeparatedSyntaxList<SyntaxNode>)tupleExpression.Arguments;
closeParen = tupleExpression.CloseParenToken;
}
public SyntaxNode GetOperandOfPrefixUnaryExpression(SyntaxNode node)
=> ((PrefixUnaryExpressionSyntax)node).Operand;
......
......@@ -229,9 +229,12 @@ public static bool IsCodeGenerationSymbol(this ISymbol symbol)
/// Creates a parameter symbol that can be used to describe a parameter declaration.
/// </summary>
public static IParameterSymbol CreateParameterSymbol(ITypeSymbol type, string name)
=> CreateParameterSymbol(RefKind.None, type, name);
public static IParameterSymbol CreateParameterSymbol(RefKind refKind, ITypeSymbol type, string name)
{
return CreateParameterSymbol(
attributes: default, refKind: RefKind.None, isParams: false, type: type, name: name, isOptional: false);
attributes: default, refKind, isParams: false, type: type, name: name, isOptional: false);
}
/// <summary>
......
......@@ -57,13 +57,7 @@ protected override CodeGenerationSymbol Clone()
public override SymbolKind Kind => SymbolKind.NamedType;
public override int Arity
{
get
{
return this.TypeParameters.Length;
}
}
public override int Arity => this.TypeParameters.Length;
public override bool IsGenericType
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.Editing;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Editing;
namespace Microsoft.CodeAnalysis.CodeGeneration
{
......@@ -33,7 +33,7 @@ public ImmutableArray<INamedTypeSymbol> AllInterfaces
public bool IsReferenceType => false;
public bool IsValueType => false;
public bool IsValueType => TypeKind == TypeKind.Struct || TypeKind == TypeKind.Enum;
public bool IsAnonymousType => false;
......
......@@ -1262,6 +1262,8 @@ public SyntaxNode RemoveNodes(SyntaxNode root, IEnumerable<SyntaxNode> declarati
#region Utility
internal abstract SeparatedSyntaxList<TElement> SeparatedList<TElement>(SyntaxNodeOrTokenList list) where TElement : SyntaxNode;
internal static SyntaxTokenList Merge(SyntaxTokenList original, SyntaxTokenList newList)
{
// return tokens from newList, but use original tokens of kind matches
......@@ -1690,6 +1692,11 @@ public SyntaxNode WithTypeArguments(SyntaxNode expression, params SyntaxNode[] t
/// </summary>
public abstract SyntaxNode QualifiedName(SyntaxNode left, SyntaxNode right);
/// <summary>
/// Returns a new name node qualified with the 'global' alias ('Global' in VB).
/// </summary>
internal abstract SyntaxNode GlobalAliasedName(SyntaxNode name);
/// <summary>
/// Creates a name expression from a dotted name string.
/// </summary>
......
......@@ -29,5 +29,6 @@ internal sealed partial class SyntaxTreeIndex
public bool ContainsBaseConstructorInitializer => _contextInfo.ContainsBaseConstructorInitializer;
public bool ContainsElementAccessExpression => _contextInfo.ContainsElementAccessExpression;
public bool ContainsIndexerMemberCref => _contextInfo.ContainsIndexerMemberCref;
public bool ContainsTupleExpressionOrTupleType => _contextInfo.ContainsTupleExpressionOrTupleType;
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Host;
namespace Microsoft.CodeAnalysis.LanguageServices
......@@ -12,6 +13,6 @@ internal interface ISymbolDeclarationService : ILanguageService
/// This differs from symbol.Locations in that Locations returns a list of ILocations that
/// normally correspond to the name node of the symbol.
/// </summary>
IEnumerable<SyntaxReference> GetDeclarations(ISymbol symbol);
ImmutableArray<SyntaxReference> GetDeclarations(ISymbol symbol);
}
}
......@@ -104,6 +104,9 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsConditionalOr(SyntaxNode node);
bool IsTupleExpression(SyntaxNode node);
void GetPartsOfTupleExpression<TArgumentSyntax>(SyntaxNode node,
out SyntaxToken openParen, out SeparatedSyntaxList<TArgumentSyntax> arguments, out SyntaxToken closeParen) where TArgumentSyntax : SyntaxNode;
bool IsTupleType(SyntaxNode node);
SyntaxNode GetOperandOfPrefixUnaryExpression(SyntaxNode node);
......
......@@ -25,6 +25,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Return SyntaxFactory.EndOfLine(text)
End Function
Friend Overrides Function SeparatedList(Of TElement As SyntaxNode)(list As SyntaxNodeOrTokenList) As SeparatedSyntaxList(Of TElement)
Return SyntaxFactory.SeparatedList(Of TElement)(list)
End Function
#Region "Expressions and Statements"
Public Overrides Function AddEventHandler([event] As SyntaxNode, handler As SyntaxNode) As SyntaxNode
......@@ -321,6 +325,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Return SyntaxFactory.QualifiedName(DirectCast(left, NameSyntax), DirectCast(right, SimpleNameSyntax))
End Function
Friend Overrides Function GlobalAliasedName(name As SyntaxNode) As SyntaxNode
Return QualifiedName(SyntaxFactory.GlobalName(), name)
End Function
Public Overrides Function ReferenceEqualsExpression(left As SyntaxNode, right As SyntaxNode) As SyntaxNode
Return SyntaxFactory.IsExpression(Parenthesize(left), Parenthesize(right))
End Function
......@@ -4148,6 +4156,5 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
End Function
#End Region
End Class
End Namespace
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Simplification
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Composition
Imports System.Threading
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis.Host
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.LanguageServices
Imports Microsoft.CodeAnalysis.Text
......@@ -18,12 +17,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' Get the declaring syntax node for a Symbol. Unlike the DeclaringSyntaxReferences property,
''' this function always returns a block syntax, if there is one.
''' </summary>
Public Function GetDeclarations(symbol As ISymbol) As IEnumerable(Of SyntaxReference) Implements ISymbolDeclarationService.GetDeclarations
If symbol Is Nothing Then
Return SpecializedCollections.EmptyEnumerable(Of SyntaxReference)()
Else
Return symbol.DeclaringSyntaxReferences.Select(Function(r) New BlockSyntaxReference(r))
End If
Public Function GetDeclarations(symbol As ISymbol) As ImmutableArray(Of SyntaxReference) Implements ISymbolDeclarationService.GetDeclarations
Return If(symbol Is Nothing,
ImmutableArray(Of SyntaxReference).Empty,
symbol.DeclaringSyntaxReferences.SelectAsArray(Of SyntaxReference)(
Function(r) New BlockSyntaxReference(r)))
End Function
''' <summary>
......
......@@ -1605,13 +1605,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
Public Function IsTupleExpression(node As syntaxnode) As Boolean Implements ISyntaxFactsService.IsTupleExpression
Return node.kind() = SyntaxKind.TupleExpression
Return node.Kind() = SyntaxKind.TupleExpression
End Function
Public Function IsTupleType(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsTupleType
Return node.Kind() = SyntaxKind.TupleType
End Function
Public Sub GetPartsOfTupleExpression(Of TArgumentSyntax As SyntaxNode)(
node As SyntaxNode, ByRef openParen As SyntaxToken, ByRef arguments As SeparatedSyntaxList(Of TArgumentSyntax), ByRef closeParen As SyntaxToken) Implements ISyntaxFactsService.GetPartsOfTupleExpression
Dim tupleExpr = DirectCast(node, TupleExpressionSyntax)
openParen = tupleExpr.OpenParenToken
arguments = CType(CType(tupleExpr.Arguments, SeparatedSyntaxList(Of SyntaxNode)), SeparatedSyntaxList(Of TArgumentSyntax))
closeParen = tupleExpr.CloseParenToken
End Sub
Public Function GetOperandOfPrefixUnaryExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetOperandOfPrefixUnaryExpression
Return DirectCast(node, UnaryExpressionSyntax).Operand
End Function
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册