FieldDelegatingCodeAction.cs 4.0 KB
Newer Older
1
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.
2 3 4 5 6 7 8 9 10 11 12

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;

C
CyrusNajmabadi 已提交
13
namespace Microsoft.CodeAnalysis.GenerateConstructorFromMembers
14
{
C
CyrusNajmabadi 已提交
15
    internal partial class GenerateConstructorFromMembersCodeRefactoringProvider
16 17 18
    {
        private class FieldDelegatingCodeAction : CodeAction
        {
C
CyrusNajmabadi 已提交
19
            private readonly GenerateConstructorFromMembersCodeRefactoringProvider _service;
20 21
            private readonly Document _document;
            private readonly State _state;
22 23

            public FieldDelegatingCodeAction(
C
CyrusNajmabadi 已提交
24
                GenerateConstructorFromMembersCodeRefactoringProvider service,
25 26 27
                Document document,
                State state)
            {
28 29 30
                _service = service;
                _document = document;
                _state = state;
31 32 33 34 35 36 37 38 39 40 41
            }

            protected override async Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
            {
                // First, see if there are any constructors that would take the first 'n' arguments
                // we've provided.  If so, delegate to those, and then create a field for any
                // remaining arguments.  Try to match from largest to smallest.
                //
                // Otherwise, just generate a normal constructor that assigns any provided
                // parameters into fields.
                var parameterToExistingFieldMap = new Dictionary<string, ISymbol>();
42
                for (int i = 0; i < _state.Parameters.Length; i++)
43
                {
44
                    parameterToExistingFieldMap[_state.Parameters[i].Name] = _state.SelectedMembers[i];
45 46
                }

47
                var factory = _document.GetLanguageService<SyntaxGenerator>();
48

49
                var syntaxTree = await _document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
50
                var members = factory.CreateFieldDelegatingConstructor(
51 52 53
                    _state.ContainingType.Name,
                    _state.ContainingType,
                    _state.Parameters,
54 55 56 57 58
                    parameterToExistingFieldMap,
                    parameterToNewFieldMap: null,
                    cancellationToken: cancellationToken);

                var result = await CodeGenerator.AddMemberDeclarationsAsync(
59 60
                    _document.Project.Solution,
                    _state.ContainingType,
61
                    members,
62 63 64 65
                    new CodeGenerationOptions(
                        contextLocation: syntaxTree.GetLocation(_state.TextSpan),
                        afterThisLocation: _state.TextSpan.IsEmpty ? syntaxTree.GetLocation(_state.TextSpan) : null),
                    cancellationToken).ConfigureAwait(false);
66 67 68 69 70 71 72 73

                return result;
            }

            public override string Title
            {
                get
                {
74 75
                    var symbolDisplayService = _document.GetLanguageService<ISymbolDisplayService>();
                    var parameters = _state.Parameters.Select(p => symbolDisplayService.ToDisplayString(p, SimpleFormat));
76 77
                    var parameterString = string.Join(", ", parameters);

78
                    if (_state.DelegatedConstructor == null)
79
                    {
80
                        return string.Format(FeaturesResources.Generate_constructor_0_1,
81
                            _state.ContainingType.Name, parameterString);
82 83 84
                    }
                    else
                    {
85
                        return string.Format(FeaturesResources.Generate_field_assigning_constructor_0_1,
86
                            _state.ContainingType.Name, parameterString);
87 88 89 90 91
                    }
                }
            }
        }
    }
92
}