Пример #1
0
        private static async Task <Solution> FixAsync(InitializeFieldsFromConstructorCodeActionContext context, CancellationToken cancellationToken)
        {
            var solution = context.Solution;
            var options  = solution.Workspace.Options;
            var document = solution.GetDocument(context.DocumentId);
            var tree     = await document.GetSyntaxTreeAsync();

            var root = tree.GetCompilationUnitRoot(cancellationToken);

            var parameter     = root.FindNode(context.Span).FirstAncestorOrSelf <ParameterSyntax>();
            var parameterName = parameter.GetParameterName();
            var fieldName     = $"_{parameterName}";

            var constructor      = parameter.FirstAncestorOrSelf <ConstructorDeclarationSyntax>();
            var classDeclaration = constructor.FirstAncestorOrSelf <ClassDeclarationSyntax>();
            var hasField         = classDeclaration.Members.OfType <FieldDeclarationSyntax>().Any(f => f.Declaration.Variables.Any(v => v.Identifier.ValueText == fieldName));

            var fieldPosition     = constructor.ParameterList.Parameters.IndexOf(parameter);
            var parameterFieldMap = constructor.ParameterList.Parameters
                                    .Select(Utilities.SyntaxExtensions.GetParameterName)
                                    .Select(pName => new
            {
                parameterName = pName,
                fieldName     = $"_{pName}"
            })
                                    .Take(fieldPosition)
                                    .ToArray();


            var constructorStatements = constructor.Body.Statements;
            var insertPosition        = 0;

            if (constructorStatements.Any())
            {
                for (var i = parameterFieldMap.Length - 1; i >= 0; i--)
                {
                    var currentParameterName = parameterFieldMap[i].parameterName;
                    var assignment           = constructorStatements
                                               .OfType <ExpressionStatementSyntax>()
                                               .Select(s => new { statement = s, expression = s.Expression as AssignmentExpressionSyntax })
                                               .Where(s => s.expression != null)
                                               .Where(a => a.expression.OperatorToken.IsKind(SyntaxKind.EqualsToken))
                                               .Where(a => a.expression.Right.IsKind(SyntaxKind.IdentifierName))
                                               .Where(a => (a.expression.Right as IdentifierNameSyntax).Identifier.ValueText == currentParameterName)
                                               .Select(a => a.statement)
                                               .FirstOrDefault();

                    if (assignment == null)
                    {
                        continue;
                    }
                    insertPosition = constructor.Body.Statements.IndexOf(assignment) + 1;
                    break;
                }
            }

            var fieldInsertPosition = 0;

            if (!hasField)
            {
                for (var i = parameterFieldMap.Length - 1; i >= 0; i--)
                {
                    var currentFieldName = parameterFieldMap[i].fieldName;
                    var fDecl            = classDeclaration.Members.OfType <FieldDeclarationSyntax>().FirstOrDefault(f => f.Declaration.Variables.Any(v => v.Identifier.ValueText == currentFieldName));
                    if (fDecl == null)
                    {
                        continue;
                    }

                    fieldInsertPosition = classDeclaration.Members.IndexOf(fDecl) + 1;
                    break;
                }
            }

            var assignStatement = Formatter.Format(
                SyntaxFactory.ExpressionStatement(
                    SyntaxFactory.AssignmentExpression(
                        SyntaxKind.SimpleAssignmentExpression,
                        SyntaxFactory.IdentifierName(fieldName),
                        SyntaxFactory.IdentifierName(parameterName)
                        )
                    ).WithTrailingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.CarriageReturnLineFeed)),
                solution.Workspace
                ) as ExpressionStatementSyntax;

            constructorStatements = constructorStatements.Insert(insertPosition, assignStatement);

            var newConstructorBody = constructor.Body.WithStatements(constructorStatements);
            var newClass           = classDeclaration.ReplaceNode(constructor.Body, newConstructorBody);

            if (!VariableExists(newClass, fieldName))
            {
                var type  = GetParameterType(parameter);
                var field = Formatter.Format(CreateFieldDeclaration(type, fieldName), solution.Workspace) as FieldDeclarationSyntax;

                newClass = newClass.WithMembers(newClass.Members.Insert(fieldInsertPosition, field));
            }

            root     = root.ReplaceNode(classDeclaration, newClass);
            document = document.WithSyntaxRoot(root);
            return(document.Project.Solution);
        }
Пример #2
0
 public InitializeFieldsFromConstructorCodeAction(InitializeFieldsFromConstructorCodeActionContext fixContext)
 {
     _fixContext = fixContext;
 }