private static Task <Document> RefactorAsync(
            Document document,
            RecordDeclarationSyntax recordDeclaration,
            CancellationToken cancellationToken = default)
        {
            ParameterListSyntax parameterList = recordDeclaration.ParameterList;
            BaseListSyntax      baseList      = recordDeclaration.BaseList;
            SeparatedSyntaxList <ParameterSyntax> parameters = parameterList.Parameters;

            var identifiersMap    = new Dictionary <string, SyntaxToken>();
            var statements        = new List <StatementSyntax>();
            var properties        = new List <PropertyDeclarationSyntax>();
            var allAttributeLists = new List <AttributeListSyntax>();

            var baseType = baseList?
                           .Types
                           .FirstOrDefault(f => f.IsKind(SyntaxKind.PrimaryConstructorBaseType)) as PrimaryConstructorBaseTypeSyntax;

            ImmutableHashSet <string> basePropertyNames = ImmutableHashSet <string> .Empty;

            if (baseType != null)
            {
                basePropertyNames = baseType
                                    .ArgumentList?
                                    .Arguments
                                    .Select(f => f.ToString())
                                    .ToImmutableHashSet();
            }

            bool isWritable = !recordDeclaration.Modifiers.Contains(SyntaxKind.ReadOnlyKeyword) &&
                              recordDeclaration.ClassOrStructKeyword.IsKind(SyntaxKind.StructKeyword);

            foreach (ParameterSyntax parameter in parameters)
            {
                SyntaxToken identifier          = parameter.Identifier;
                string      identifierText      = identifier.ValueText;
                SyntaxToken parameterIdentifier = Identifier(StringUtility.FirstCharToLower(identifierText));
                SyntaxToken propertyIdentifier  = Identifier(StringUtility.FirstCharToUpper(identifierText));
                identifiersMap.Add(identifier.ValueText, parameterIdentifier);

                IEnumerable <AttributeListSyntax> attributeLists = parameter.AttributeLists.Where(f => f.Target?.Identifier.IsKind(SyntaxKind.PropertyKeyword) == true);

                allAttributeLists.AddRange(attributeLists);

                statements.Add(SimpleAssignmentStatement(
                                   IdentifierName(propertyIdentifier).QualifyWithThis(),
                                   IdentifierName(parameterIdentifier.WithTriviaFrom(identifier))));

                if (!basePropertyNames.Contains(identifierText))
                {
                    properties.Add(PropertyDeclaration(
                                       attributeLists.Select(f => f.WithTarget(null)).ToSyntaxList(),
                                       Modifiers.Public(),
                                       parameter.Type,
                                       default(ExplicitInterfaceSpecifierSyntax),
                                       propertyIdentifier,
                                       AccessorList(
                                           AutoGetAccessorDeclaration(),
                                           (isWritable) ? AutoSetAccessorDeclaration() : AutoInitAccessorDeclaration()
                                           )));
                }
            }

            ParameterListSyntax newParameterList = parameterList.RemoveNodes(
                allAttributeLists,
                SyntaxRemoveOptions.KeepLeadingTrivia | SyntaxRemoveOptions.KeepUnbalancedDirectives);

            newParameterList = newParameterList.ReplaceTokens(
                newParameterList.Parameters.Select(parameter => parameter.Identifier),
                (identifier, _) => identifiersMap[identifier.ValueText]);

            ParameterSyntax firstParameter = parameterList.Parameters[0];

            if (firstParameter.GetLeadingTrivia().SingleOrDefault(shouldThrow: false).IsKind(SyntaxKind.WhitespaceTrivia))
            {
                SyntaxTriviaList newIndentation = SyntaxTriviaAnalysis.GetIncreasedIndentationTriviaList(firstParameter, cancellationToken);

                newParameterList = newParameterList.ReplaceNodes(
                    newParameterList.Parameters,
                    (parameter, _) =>
                {
                    return((parameter.GetLeadingTrivia().SingleOrDefault().IsKind(SyntaxKind.WhitespaceTrivia))
                            ? parameter.WithLeadingTrivia(newIndentation)
                            : parameter);
                });
            }

            ConstructorDeclarationSyntax constructor = ConstructorDeclaration(
                Modifiers.Public(),
                recordDeclaration.Identifier.WithoutTrivia(),
                newParameterList,
                Block(statements));

            RecordDeclarationSyntax newRecord = recordDeclaration
                                                .WithIdentifier(recordDeclaration.Identifier.WithTrailingTrivia(recordDeclaration.ParameterList.GetTrailingTrivia()))
                                                .WithParameterList(null)
                                                .WithSemicolonToken(default);
示例#2
0
        public static ParameterListSyntax WithoutAttributes(this ParameterListSyntax parameterList)
        {
            var methodParameterAttributes = parameterList.Parameters.SelectMany(p => p.AttributeLists);

            return(parameterList.RemoveNodes(methodParameterAttributes, SyntaxRemoveOptions.KeepNoTrivia));
        }