Esempio n. 1
0
        private static SyntaxNode SetNewType(SyntaxNode node, TypeSyntax newType)
        {
            switch (node.Kind())
            {
            case SyntaxKind.MethodDeclaration:
            {
                var declaration = (MethodDeclarationSyntax)node;
                return(declaration.WithReturnType(newType.WithTriviaFrom(declaration.ReturnType)));
            }

            case SyntaxKind.PropertyDeclaration:
            {
                var declaration = (PropertyDeclarationSyntax)node;
                return(declaration.WithType(newType.WithTriviaFrom(declaration.Type)));
            }

            case SyntaxKind.IndexerDeclaration:
            {
                var declaration = (IndexerDeclarationSyntax)node;
                return(declaration.WithType(newType.WithTriviaFrom(declaration.Type)));
            }

            default:
            {
                return(null);
            }
            }
        }
            static TSyntaxNode ReplaceNodes <TSyntaxNode>(TSyntaxNode node, string name, TypeSyntax replacement)
                where TSyntaxNode : SyntaxNode
            {
                var uses = node.DescendantNodesAndSelf().OfType <SimpleNameSyntax>().Where(i => i.Identifier.ValueText == name).ToList();

                return(node.ReplaceNodes(uses, (old, _) => replacement.WithTriviaFrom(old)));
            }
Esempio n. 3
0
        private static async Task <Document> FixIncorrectCastAsync(Document document, CastExpressionSyntax cast, string requiredType, CancellationToken cancellationToken)
        {
            // Split the type name into its namespace and type.
            QualifiedNameSyntax qualifiedName = (QualifiedNameSyntax)SyntaxFactory.ParseTypeName(requiredType);
            NameSyntax          namespaceName = qualifiedName.Left;
            TypeSyntax          type          = qualifiedName.Right;

            // Change the type in the cast statement.
            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken);

            CastExpressionSyntax?newCast = cast.WithType(type.WithTriviaFrom(cast.Type));

            // Update the cast statement and, if required, change the
            // type of the variable that the cast is being assigned to.
            root = await ReplaceNodeAndUpdateVariableTypeAsync(document, root, cast, newCast, type, cancellationToken);

            // Add a using directive for the namespace
            // if the namespace is not already imported.
            if (root is CompilationUnitSyntax unit)
            {
                root = unit.WithUsings(AddUsingDirectiveIfMissing(unit.Usings, namespaceName));
            }

            return(document.WithSyntaxRoot(root));
        }
Esempio n. 4
0
        public static async Task <Document> ChangeTypeAsync(
            Document document,
            TypeSyntax type,
            TypeSyntax newType,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (newType == null)
            {
                throw new ArgumentNullException(nameof(newType));
            }

            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            newType = newType
                      .WithTriviaFrom(type)
                      .WithSimplifierAnnotation();

            SyntaxNode newRoot = root.ReplaceNode(type, newType);

            return(document.WithSyntaxRoot(newRoot));
        }
        private static Task <Document> RefactorAsync(
            Document document,
            LocalDeclarationStatementSyntax localDeclarationStatement,
            ExpressionSyntax value,
            ITypeSymbol typeSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            int position = localDeclarationStatement.SpanStart;

            ExpressionSyntax defaultValue = typeSymbol.GetDefaultValueSyntax(semanticModel, position);

            LocalDeclarationStatementSyntax newNode = localDeclarationStatement.ReplaceNode(
                value,
                defaultValue.WithTriviaFrom(value));

            TypeSyntax oldType = newNode.Declaration.Type;

            if (oldType.IsVar &&
                !defaultValue.IsKind(SyntaxKind.DefaultExpression, SyntaxKind.SimpleMemberAccessExpression))
            {
                TypeSyntax type = typeSymbol.ToMinimalTypeSyntax(semanticModel, position);

                newNode = newNode.ReplaceNode(oldType, type.WithTriviaFrom(oldType));
            }

            return(document.ReplaceNodeAsync(localDeclarationStatement, newNode, cancellationToken));
        }
        public static void ChangeLocalFunctionReturnType(
            CodeFixContext context,
            Diagnostic diagnostic,
            LocalFunctionStatementSyntax localFunction,
            ITypeSymbol typeSymbol,
            SemanticModel semanticModel,
            string additionalKey = null)
        {
            if (typeSymbol.IsErrorType())
            {
                return;
            }

            Document document = context.Document;

            CodeAction codeAction = CodeAction.Create(
                $"Change return type to '{SymbolDisplay.ToMinimalDisplayString(typeSymbol, semanticModel, localFunction.SpanStart, SymbolDisplayFormats.Default)}'",
                cancellationToken =>
            {
                TypeSyntax newType = typeSymbol.ToMinimalTypeSyntax(semanticModel, localFunction.SpanStart);

                LocalFunctionStatementSyntax newNode = localFunction.WithReturnType(newType.WithTriviaFrom(localFunction.ReturnType));

                return(document.ReplaceNodeAsync(localFunction, newNode, cancellationToken));
            },
                EquivalenceKey.Create(diagnostic, additionalKey));

            context.RegisterCodeFix(codeAction, diagnostic);
        }
        public static async Task <Document> RefactorAsync(
            Document document,
            LocalDeclarationStatementSyntax localDeclaration,
            CancellationToken cancellationToken)
        {
            TypeSyntax type = localDeclaration.Declaration.Type;

            LocalDeclarationStatementSyntax newNode = localDeclaration;

            if (type.IsVar)
            {
                SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, cancellationToken);

                TypeSyntax newType = typeSymbol.ToMinimalTypeSyntax(semanticModel, localDeclaration.SpanStart);

                newNode = newNode.ReplaceNode(type, newType.WithTriviaFrom(type));
            }

            Debug.Assert(!newNode.Modifiers.Any(), newNode.Modifiers.ToString());

            if (newNode.Modifiers.Any())
            {
                newNode = newNode.InsertModifier(SyntaxKind.ConstKeyword);
            }
            else
            {
                newNode = newNode
                          .WithoutLeadingTrivia()
                          .WithModifiers(TokenList(Token(SyntaxKind.ConstKeyword).WithLeadingTrivia(newNode.GetLeadingTrivia())));
            }

            return(await document.ReplaceNodeAsync(localDeclaration, newNode, cancellationToken).ConfigureAwait(false));
        }
Esempio n. 8
0
 public static Task <Document> ChangeTypeAsync(
     Document document,
     TypeSyntax type,
     TypeSyntax newType,
     CancellationToken cancellationToken = default(CancellationToken))
 {
     return(document.ReplaceNodeAsync(type, newType.WithTriviaFrom(type), cancellationToken));
 }
        private static Task <Document> RefactorAsync(
            Document document,
            VariableDeclarationSyntax variableDeclaration,
            INamedTypeSymbol typeSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            TypeSyntax type = typeSymbol.ToMinimalTypeSyntax(semanticModel, variableDeclaration.SpanStart);

            VariableDeclarationSyntax newNode = variableDeclaration.WithType(type.WithTriviaFrom(variableDeclaration.Type));

            return(document.ReplaceNodeAsync(variableDeclaration, newNode, cancellationToken));
        }
        private static Task <Document> RefactorAsync(
            Document document,
            SingleLocalDeclarationStatementInfo localInfo,
            TypeSyntax type,
            CancellationToken cancellationToken)
        {
            LocalDeclarationStatementSyntax localStatement = localInfo.Statement;

            StatementsInfo statementsInfo = SyntaxInfo.StatementsInfo(localStatement);

            int index = statementsInfo.IndexOf(localStatement);

            VariableDeclaratorSyntax declarator = localInfo.Declarator;

            VariableDeclaratorSyntax newDeclarator = declarator.WithInitializer(null);

            VariableDeclarationSyntax newDeclaration = localInfo.Declaration.ReplaceNode(declarator, newDeclarator);

            if (type != null)
            {
                newDeclaration = newDeclaration.WithType(type.WithTriviaFrom(newDeclaration.Type));
            }

            LocalDeclarationStatementSyntax newLocalStatement = localStatement
                                                                .WithDeclaration(newDeclaration)
                                                                .WithTrailingTrivia(NewLine())
                                                                .WithFormatterAnnotation();

            ExpressionStatementSyntax assignmentStatement = SimpleAssignmentStatement(IdentifierName(localInfo.Identifier), localInfo.Initializer.Value)
                                                            .WithTrailingTrivia(localStatement.GetTrailingTrivia())
                                                            .WithFormatterAnnotation();

            StatementsInfo newStatementsInfo = statementsInfo
                                               .Insert(index + 1, assignmentStatement)
                                               .ReplaceAt(index, newLocalStatement);

            return(document.ReplaceStatementsAsync(statementsInfo, newStatementsInfo, cancellationToken));
        }
        public static Task <Document> ChangeTypeAsync(
            Document document,
            TypeSyntax type,
            TypeSyntax newType,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (newType == null)
            {
                throw new ArgumentNullException(nameof(newType));
            }

            return(document.ReplaceNodeAsync(type, newType.WithTriviaFrom(type), cancellationToken));
        }
Esempio n. 12
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsAnyCodeFixEnabled(
                    CodeFixIdentifiers.AddArgumentList,
                    CodeFixIdentifiers.ChangeArrayType))
            {
                return;
            }

            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(root, context.Span, out SimpleNameSyntax simpleName))
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.CannotConvertMethodGroupToNonDelegateType:
                {
                    if (!simpleName.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
                    {
                        break;
                    }

                    var memberAccess = (MemberAccessExpressionSyntax)simpleName.Parent;

                    CodeAction codeAction = CodeAction.Create(
                        "Add argument list",
                        cancellationToken =>
                        {
                            InvocationExpressionSyntax invocationExpression = InvocationExpression(
                                memberAccess.WithoutTrailingTrivia(),
                                ArgumentList().WithTrailingTrivia(memberAccess.GetTrailingTrivia()));

                            return(context.Document.ReplaceNodeAsync(memberAccess, invocationExpression, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.TypeOrNamespaceNameCouldNotBeFound:
                {
                    if (!(simpleName.Parent is ArrayTypeSyntax arrayType))
                    {
                        break;
                    }

                    if (!(arrayType.Parent is ArrayCreationExpressionSyntax arrayCreation))
                    {
                        break;
                    }

                    if (!object.ReferenceEquals(simpleName, arrayType.ElementType))
                    {
                        break;
                    }

                    ExpressionSyntax expression = arrayCreation.Initializer?.Expressions.FirstOrDefault();

                    if (expression == null)
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression, context.CancellationToken);

                    if (typeSymbol?.SupportsExplicitDeclaration() != true)
                    {
                        break;
                    }

                    TypeSyntax newType = typeSymbol.ToMinimalTypeSyntax(semanticModel, simpleName.SpanStart);

                    CodeAction codeAction = CodeAction.Create(
                        $"Change element type to '{SymbolDisplay.ToMinimalDisplayString(typeSymbol, semanticModel, simpleName.SpanStart, SymbolDisplayFormats.Default)}'",
                        cancellationToken => context.Document.ReplaceNodeAsync(simpleName, newType.WithTriviaFrom(simpleName), cancellationToken),
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
Esempio n. 13
0
        static void BindEnumerableAndEnumerator(EnumerableDetails details, TypeSyntax newOutType, out TypeSyntax updatedEnumerable, out TypeSyntax updatedEnumerator)
        {
            var baseEnumerable = details.BridgeEnumerable;
            var baseEnumerator = details.BridgeEnumerator;

            var enumerableMentionsOfOutType = baseEnumerable.DescendantNodesAndSelf().OfType <SimpleNameSyntax>().Where(i => i.Identifier.ValueText == details.OutItem).ToList();
            var enumeratorMentionsOfOutType = baseEnumerator.DescendantNodesAndSelf().OfType <SimpleNameSyntax>().Where(i => i.Identifier.ValueText == details.OutItem).ToList();

            updatedEnumerable = baseEnumerable.ReplaceNodes(enumerableMentionsOfOutType, (old, _) => newOutType.WithTriviaFrom(old));
            updatedEnumerator = baseEnumerator.ReplaceNodes(enumeratorMentionsOfOutType, (old, _) => newOutType.WithTriviaFrom(old));
        }
        private static Task <Document> RefactorAsync(
            Document document,
            CastExpressionSyntax castExpression,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax expression = castExpression.Expression;
            TypeSyntax       type       = castExpression.Type;

            BinaryExpressionSyntax newNode = CSharpFactory.AsExpression(expression.WithTriviaFrom(type), type.WithTriviaFrom(expression))
                                             .WithTriviaFrom(castExpression)
                                             .WithFormatterAnnotation();

            return(document.ReplaceNodeAsync(castExpression, newNode, cancellationToken));
        }
Esempio n. 15
0
        static MethodDeclarationSyntax InjectIdentityAndEnumerator(MethodDeclarationSyntax mtd, TypeSyntax enumerable, TypeSyntax enumerator)
        {
            var updated = mtd;

            // replace calls to CommonImplementation methods so that the appropriate enumerable and enumerators
            //   are used
            var commonNonBridge =
                (updated.Body?.DescendantNodesAndSelf() ??
                 updated.ExpressionBody?.DescendantNodesAndSelf()
                )
                .OfType <InvocationExpressionSyntax>()
                .Where(o => o.Expression is MemberAccessExpressionSyntax)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Expression is IdentifierNameSyntax)
                .Where(o => ((IdentifierNameSyntax)((MemberAccessExpressionSyntax)o.Expression).Expression).Identifier.ValueText == COMMON_IMPLEMENTATION_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != BRIDGE_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != FORBIDDEN_CALL_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != UNEXPECTED_PATH_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != UNINITIALIZED_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != ARGUMENT_NULL_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != SEQUENCE_EMPTY_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != OUT_OF_RANGE_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != NO_ITEMS_MATCHED_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != MULTIPLE_MATCHING_ELEMENTS_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != MULTIPLE_ELEMENTS_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != UNINITIALIZED_PROJECTION_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != UNEXPECTED_STATE_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != NOT_IMPLEMENTED_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != INNER_UNINITIALIZED_NAME)
                .Where(o => ((MemberAccessExpressionSyntax)o.Expression).Name.Identifier.ValueText != INVALID_OPERATION_NAME)
                .ToList();

            var replacements = new Dictionary <InvocationExpressionSyntax, InvocationExpressionSyntax>();

            foreach (var invocation in commonNonBridge)
            {
                var method = ((MemberAccessExpressionSyntax)invocation.Expression).Name;
                GenericNameSyntax genericMethod;
                if (method is GenericNameSyntax)
                {
                    genericMethod = (GenericNameSyntax)method;
                }
                else
                {
                    genericMethod = SyntaxFactory.GenericName(method.Identifier);
                }

                var withMoreTerms     = genericMethod.AddTypeArgumentListArguments(enumerable, enumerator);
                var commonAccess      = ((MemberAccessExpressionSyntax)invocation.Expression).WithName(withMoreTerms);
                var updatedInvocation = invocation.WithExpression(commonAccess);

                replacements[invocation] = updatedInvocation;
            }

            updated = updated.ReplaceNodes(replacements.Keys, (old, _) => replacements[old].WithTriviaFrom(old));

            var retVal = updated.ReturnType;

            if (retVal != null)
            {
                var updatedRetVal = retVal;

                var mentionsOfEnumerable = updatedRetVal.DescendantNodesAndSelf().OfType <SimpleNameSyntax>().Where(t => t.Identifier.ValueText == BUILTIN_ENUMERABLE_NAME).ToList();
                updatedRetVal = updatedRetVal.ReplaceNodes(mentionsOfEnumerable, (old, _) => enumerable.WithTriviaFrom(old));

                var mentionsOfEnumerator = updatedRetVal.DescendantNodesAndSelf().OfType <SimpleNameSyntax>().Where(t => t.Identifier.ValueText == BUILTIN_ENUMERATOR_NAME).ToList();
                updatedRetVal = updatedRetVal.ReplaceNodes(mentionsOfEnumerator, (old, _) => enumerator.WithTriviaFrom(old));

                updated = updated.WithReturnType(updatedRetVal.WithTriviaFrom(retVal));
            }

            return(updated);
        }
Esempio n. 16
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsAnyCodeFixEnabled(
                    CodeFixIdentifiers.AddArgumentList,
                    CodeFixIdentifiers.ReorderModifiers,
                    CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue,
                    CodeFixIdentifiers.ReturnDefaultValue,
                    CodeFixIdentifiers.AddMissingType))
            {
                return;
            }

            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindToken(root, context.Span.Start, out SyntaxToken token))
            {
                return;
            }

            SyntaxKind kind = token.Kind();

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.OperatorCannotBeAppliedToOperandOfType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddArgumentList))
                    {
                        break;
                    }

                    if (kind != SyntaxKind.QuestionToken)
                    {
                        break;
                    }

                    if (!token.IsParentKind(SyntaxKind.ConditionalAccessExpression))
                    {
                        break;
                    }

                    var conditionalAccess = (ConditionalAccessExpressionSyntax)token.Parent;

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(conditionalAccess.Expression, context.CancellationToken);

                    if (typeSymbol == null ||
                        typeSymbol.IsErrorType() ||
                        !typeSymbol.IsValueType ||
                        typeSymbol.IsConstructedFrom(SpecialType.System_Nullable_T))
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Remove '?' operator",
                        cancellationToken =>
                        {
                            var textChange = new TextChange(token.Span, "");
                            return(context.Document.WithTextChangeAsync(textChange, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.PartialModifierCanOnlyAppearImmediatelyBeforeClassStructInterfaceOrVoid:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReorderModifiers))
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.MoveModifier(context, diagnostic, token.Parent, token);
                    break;
                }

                case CompilerDiagnosticIdentifiers.ValueCannotBeUsedAsDefaultParameter:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue))
                    {
                        break;
                    }

                    if (!(token.Parent is ParameterSyntax parameter))
                    {
                        break;
                    }

                    ExpressionSyntax value = parameter.Default?.Value;

                    if (value == null)
                    {
                        break;
                    }

                    if (value.Kind() != SyntaxKind.NullLiteralExpression)
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    CodeFixRegistrator.ReplaceNullWithDefaultValue(context, diagnostic, value, semanticModel);
                    break;
                }

                case CompilerDiagnosticIdentifiers.ObjectOfTypeConvertibleToTypeIsRequired:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReturnDefaultValue))
                    {
                        break;
                    }

                    if (token.Kind() != SyntaxKind.ReturnKeyword)
                    {
                        break;
                    }

                    if (!token.IsParentKind(SyntaxKind.ReturnStatement))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ISymbol symbol = semanticModel.GetEnclosingSymbol(token.SpanStart, context.CancellationToken);

                    if (symbol == null)
                    {
                        break;
                    }

                    SymbolKind symbolKind = symbol.Kind;

                    ITypeSymbol typeSymbol = null;

                    if (symbolKind == SymbolKind.Method)
                    {
                        var methodSymbol = (IMethodSymbol)symbol;

                        typeSymbol = methodSymbol.ReturnType;

                        if (methodSymbol.IsAsync &&
                            (typeSymbol is INamedTypeSymbol namedTypeSymbol))
                        {
                            ImmutableArray <ITypeSymbol> typeArguments = namedTypeSymbol.TypeArguments;

                            if (typeArguments.Any())
                            {
                                typeSymbol = typeArguments[0];
                            }
                        }
                    }
                    else if (symbolKind == SymbolKind.Property)
                    {
                        typeSymbol = ((IPropertySymbol)symbol).Type;
                    }
                    else
                    {
                        Debug.Fail(symbolKind.ToString());
                    }

                    if (typeSymbol == null)
                    {
                        break;
                    }

                    if (typeSymbol.Kind == SymbolKind.ErrorType)
                    {
                        break;
                    }

                    if (!typeSymbol.SupportsExplicitDeclaration())
                    {
                        break;
                    }

                    var returnStatement = (ReturnStatementSyntax)token.Parent;

                    CodeAction codeAction = CodeAction.Create(
                        "Return default value",
                        cancellationToken =>
                        {
                            ExpressionSyntax expression = typeSymbol.ToDefaultValueSyntax(semanticModel, returnStatement.SpanStart);

                            ReturnStatementSyntax newNode = returnStatement.WithExpression(expression);

                            return(context.Document.ReplaceNodeAsync(returnStatement, newNode, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.TypeExpected:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddMissingType))
                    {
                        break;
                    }

                    if (token.Kind() != SyntaxKind.CloseParenToken)
                    {
                        break;
                    }

                    if (!(token.Parent is DefaultExpressionSyntax defaultExpression))
                    {
                        break;
                    }

                    if (!(defaultExpression.Type is IdentifierNameSyntax identifierName))
                    {
                        break;
                    }

                    if (!identifierName.IsMissing)
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    TypeInfo typeInfo = semanticModel.GetTypeInfo(defaultExpression, context.CancellationToken);

                    ITypeSymbol convertedType = typeInfo.ConvertedType;

                    if (convertedType?.SupportsExplicitDeclaration() != true)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        $"Add type '{SymbolDisplay.GetMinimalString(convertedType, semanticModel, defaultExpression.SpanStart)}'",
                        cancellationToken =>
                        {
                            TypeSyntax newNode = convertedType.ToMinimalTypeSyntax(semanticModel, defaultExpression.SpanStart);

                            newNode = newNode
                                      .WithTriviaFrom(identifierName)
                                      .WithFormatterAnnotation();

                            return(context.Document.ReplaceNodeAsync(identifierName, newNode, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
        public static TypeSyntax GetMappedType(this TypeSyntax type, TypeInfo typeInfo)
        {
            TypeSyntax mappedType = typeInfo.GetMappedType();

            return(mappedType.ToString() == type.ToString() ? type : mappedType.WithTriviaFrom(type));
        }
Esempio n. 18
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddArgumentList) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReorderModifiers) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReturnDefaultValue) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddMissingType) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveSemicolon) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConditionalAccess) &&
                !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeForEachType))
            {
                return;
            }

            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindToken(root, context.Span.Start, out SyntaxToken token))
            {
                return;
            }

            SyntaxKind kind = token.Kind();

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.OperatorCannotBeAppliedToOperandOfType:
                {
                    if (kind == SyntaxKind.QuestionToken &&
                        token.Parent is ConditionalAccessExpressionSyntax conditionalAccess)
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(conditionalAccess.Expression, context.CancellationToken);

                        if (typeSymbol?.IsErrorType() == false &&
                            !typeSymbol.IsConstructedFrom(SpecialType.System_Nullable_T))
                        {
                            if (typeSymbol.IsValueType)
                            {
                                if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConditionalAccess))
                                {
                                    CodeAction codeAction = CodeAction.Create(
                                        "Remove '?' operator",
                                        cancellationToken =>
                                        {
                                            var textChange = new TextChange(token.Span, "");
                                            return(context.Document.WithTextChangeAsync(textChange, cancellationToken));
                                        },
                                        GetEquivalenceKey(diagnostic));

                                    context.RegisterCodeFix(codeAction, diagnostic);
                                }
                            }
                            else if (typeSymbol.IsReferenceType)
                            {
                                if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddArgumentList) &&
                                    conditionalAccess.WhenNotNull is MemberBindingExpressionSyntax memberBindingExpression)
                                {
                                    ConditionalAccessExpressionSyntax newNode = conditionalAccess.WithWhenNotNull(
                                        InvocationExpression(
                                            memberBindingExpression.WithoutTrailingTrivia(),
                                            ArgumentList().WithTrailingTrivia(memberBindingExpression.GetTrailingTrivia())));

                                    CodeAction codeAction = CodeAction.Create(
                                        "Add argument list",
                                        cancellationToken => context.Document.ReplaceNodeAsync(conditionalAccess, newNode, cancellationToken),
                                        GetEquivalenceKey(diagnostic));

                                    context.RegisterCodeFix(codeAction, diagnostic);
                                }
                            }
                        }

                        if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddArgumentList))
                        {
                            break;
                        }

                        if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConditionalAccess))
                        {
                        }
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.PartialModifierCanOnlyAppearImmediatelyBeforeClassStructInterfaceOrVoid:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReorderModifiers))
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.MoveModifier(context, diagnostic, token.Parent, token);
                    break;
                }

                case CompilerDiagnosticIdentifiers.ValueCannotBeUsedAsDefaultParameter:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue))
                    {
                        break;
                    }

                    if (!(token.Parent is ParameterSyntax parameter))
                    {
                        break;
                    }

                    ExpressionSyntax value = parameter.Default?.Value;

                    if (value == null)
                    {
                        break;
                    }

                    if (value.Kind() != SyntaxKind.NullLiteralExpression)
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    CodeFixRegistrator.ReplaceNullWithDefaultValue(context, diagnostic, value, semanticModel);
                    break;
                }

                case CompilerDiagnosticIdentifiers.ObjectOfTypeConvertibleToTypeIsRequired:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReturnDefaultValue))
                    {
                        break;
                    }

                    if (token.Kind() != SyntaxKind.ReturnKeyword)
                    {
                        break;
                    }

                    if (!token.IsParentKind(SyntaxKind.ReturnStatement))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ISymbol symbol = semanticModel.GetEnclosingSymbol(token.SpanStart, context.CancellationToken);

                    if (symbol == null)
                    {
                        break;
                    }

                    SymbolKind symbolKind = symbol.Kind;

                    ITypeSymbol typeSymbol = null;

                    if (symbolKind == SymbolKind.Method)
                    {
                        var methodSymbol = (IMethodSymbol)symbol;

                        typeSymbol = methodSymbol.ReturnType;

                        if (methodSymbol.IsAsync &&
                            (typeSymbol is INamedTypeSymbol namedTypeSymbol))
                        {
                            ImmutableArray <ITypeSymbol> typeArguments = namedTypeSymbol.TypeArguments;

                            if (typeArguments.Any())
                            {
                                typeSymbol = typeArguments[0];
                            }
                        }
                    }
                    else if (symbolKind == SymbolKind.Property)
                    {
                        typeSymbol = ((IPropertySymbol)symbol).Type;
                    }
                    else
                    {
                        Debug.Fail(symbolKind.ToString());
                    }

                    if (typeSymbol == null)
                    {
                        break;
                    }

                    if (typeSymbol.Kind == SymbolKind.ErrorType)
                    {
                        break;
                    }

                    if (!typeSymbol.SupportsExplicitDeclaration())
                    {
                        break;
                    }

                    var returnStatement = (ReturnStatementSyntax)token.Parent;

                    CodeAction codeAction = CodeAction.Create(
                        "Return default value",
                        cancellationToken =>
                        {
                            ExpressionSyntax expression = typeSymbol.ToDefaultValueSyntax(semanticModel, returnStatement.SpanStart);

                            ReturnStatementSyntax newNode = returnStatement.WithExpression(expression);

                            return(context.Document.ReplaceNodeAsync(returnStatement, newNode, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.TypeExpected:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddMissingType))
                    {
                        break;
                    }

                    if (token.Kind() != SyntaxKind.CloseParenToken)
                    {
                        break;
                    }

                    if (!(token.Parent is DefaultExpressionSyntax defaultExpression))
                    {
                        break;
                    }

                    if (!(defaultExpression.Type is IdentifierNameSyntax identifierName))
                    {
                        break;
                    }

                    if (!identifierName.IsMissing)
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    TypeInfo typeInfo = semanticModel.GetTypeInfo(defaultExpression, context.CancellationToken);

                    ITypeSymbol convertedType = typeInfo.ConvertedType;

                    if (convertedType?.SupportsExplicitDeclaration() != true)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        $"Add type '{SymbolDisplay.GetMinimalString(convertedType, semanticModel, defaultExpression.SpanStart)}'",
                        cancellationToken =>
                        {
                            TypeSyntax newNode = convertedType.ToMinimalTypeSyntax(semanticModel, defaultExpression.SpanStart);

                            newNode = newNode
                                      .WithTriviaFrom(identifierName)
                                      .WithFormatterAnnotation();

                            return(context.Document.ReplaceNodeAsync(identifierName, newNode, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.SemicolonAfterMethodOrAccessorBlockIsNotValid:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveSemicolon))
                    {
                        break;
                    }

                    if (token.Kind() != SyntaxKind.SemicolonToken)
                    {
                        break;
                    }

                    switch (token.Parent)
                    {
                    case MethodDeclarationSyntax methodDeclaration:
                    {
                        BlockSyntax body = methodDeclaration.Body;

                        if (body == null)
                        {
                            break;
                        }

                        CodeAction codeAction = CodeAction.Create(
                            "Remove semicolon",
                            cancellationToken =>
                                {
                                    SyntaxTriviaList trivia = body
                                                              .GetTrailingTrivia()
                                                              .EmptyIfWhitespace()
                                                              .AddRange(token.LeadingTrivia.EmptyIfWhitespace())
                                                              .AddRange(token.TrailingTrivia);

                                    MethodDeclarationSyntax newNode = methodDeclaration
                                                                      .WithBody(body.WithTrailingTrivia(trivia))
                                                                      .WithSemicolonToken(default(SyntaxToken));

                                    return(context.Document.ReplaceNodeAsync(methodDeclaration, newNode, cancellationToken));
                                },
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                        break;
                    }

                    case PropertyDeclarationSyntax propertyDeclaration:
                    {
                        AccessorListSyntax accessorList = propertyDeclaration.AccessorList;

                        if (accessorList == null)
                        {
                            break;
                        }

                        CodeAction codeAction = CodeAction.Create(
                            "Remove semicolon",
                            cancellationToken =>
                                {
                                    SyntaxTriviaList trivia = accessorList
                                                              .GetTrailingTrivia()
                                                              .EmptyIfWhitespace()
                                                              .AddRange(token.LeadingTrivia.EmptyIfWhitespace())
                                                              .AddRange(token.TrailingTrivia);

                                    PropertyDeclarationSyntax newNode = propertyDeclaration
                                                                        .WithAccessorList(accessorList.WithTrailingTrivia(trivia))
                                                                        .WithSemicolonToken(default(SyntaxToken));

                                    return(context.Document.ReplaceNodeAsync(propertyDeclaration, newNode, cancellationToken));
                                },
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                        break;
                    }

                    case AccessorDeclarationSyntax accessorDeclaration:
                    {
                        BlockSyntax body = accessorDeclaration.Body;

                        if (body == null)
                        {
                            break;
                        }

                        CodeAction codeAction = CodeAction.Create(
                            "Remove semicolon",
                            cancellationToken =>
                                {
                                    SyntaxTriviaList trivia = body
                                                              .GetTrailingTrivia()
                                                              .EmptyIfWhitespace()
                                                              .AddRange(token.LeadingTrivia.EmptyIfWhitespace())
                                                              .AddRange(token.TrailingTrivia);

                                    AccessorDeclarationSyntax newNode = accessorDeclaration
                                                                        .WithBody(body.WithTrailingTrivia(trivia))
                                                                        .WithSemicolonToken(default(SyntaxToken));

                                    return(context.Document.ReplaceNodeAsync(accessorDeclaration, newNode, cancellationToken));
                                },
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                        break;
                    }
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.CannotConvertType:
                {
                    if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeForEachType))
                    {
                        break;
                    }

                    if (token.Kind() != SyntaxKind.ForEachKeyword)
                    {
                        break;
                    }

                    if (!(token.Parent is ForEachStatementSyntax forEachStatement))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ForEachStatementInfo info = semanticModel.GetForEachStatementInfo(forEachStatement);

                    ITypeSymbol typeSymbol = info.ElementType;

                    if (typeSymbol.SupportsExplicitDeclaration())
                    {
                        CodeFixRegistrator.ChangeType(context, diagnostic, forEachStatement.Type, typeSymbol, semanticModel, CodeFixIdentifiers.ChangeForEachType);
                    }

                    CodeFixRegistrator.ChangeTypeToVar(context, diagnostic, forEachStatement.Type, CodeFixIdentifiers.ChangeTypeToVar);
                    break;
                }
                }
            }
        }
        public static void ChangeMemberDeclarationType(
            CodeFixContext context,
            Diagnostic diagnostic,
            MemberDeclarationSyntax memberDeclaration,
            ITypeSymbol typeSymbol,
            SemanticModel semanticModel,
            string additionalKey = null)
        {
            if (typeSymbol.IsErrorType())
            {
                return;
            }

            Document document = context.Document;

            string typeName = SymbolDisplay.ToMinimalDisplayString(typeSymbol, semanticModel, memberDeclaration.SpanStart, SymbolDisplayFormats.Default);

            string title = (memberDeclaration.IsKind(SyntaxKind.MethodDeclaration))
                ? $"Change return type to '{typeName}'"
                : $"Change type to '{typeName}'";

            CodeAction codeAction = CodeAction.Create(
                title,
                cancellationToken => RefactorAsync(cancellationToken),
                EquivalenceKey.Create(diagnostic, additionalKey));

            context.RegisterCodeFix(codeAction, diagnostic);

            Task <Document> RefactorAsync(CancellationToken cancellationToken)
            {
                TypeSyntax newType = typeSymbol.ToMinimalTypeSyntax(semanticModel, memberDeclaration.SpanStart);

                switch (memberDeclaration.Kind())
                {
                case SyntaxKind.MethodDeclaration:
                {
                    var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration;

                    MethodDeclarationSyntax newNode = methodDeclaration.WithReturnType(newType.WithTriviaFrom(methodDeclaration.ReturnType));

                    return(document.ReplaceNodeAsync(methodDeclaration, newNode, cancellationToken));
                }

                case SyntaxKind.PropertyDeclaration:
                {
                    var propertyDeclaration = (PropertyDeclarationSyntax)memberDeclaration;

                    PropertyDeclarationSyntax newNode = propertyDeclaration.WithType(newType.WithTriviaFrom(propertyDeclaration.Type));

                    return(document.ReplaceNodeAsync(propertyDeclaration, newNode, cancellationToken));
                }

                case SyntaxKind.IndexerDeclaration:
                {
                    var indexerDeclaration = (IndexerDeclarationSyntax)memberDeclaration;

                    IndexerDeclarationSyntax newNode = indexerDeclaration.WithType(newType.WithTriviaFrom(indexerDeclaration.Type));

                    return(document.ReplaceNodeAsync(indexerDeclaration, newNode, cancellationToken));
                }

                case SyntaxKind.EventDeclaration:
                {
                    var eventDeclaration = (EventDeclarationSyntax)memberDeclaration;

                    EventDeclarationSyntax newNode = eventDeclaration.WithType(newType.WithTriviaFrom(eventDeclaration.Type));

                    return(document.ReplaceNodeAsync(eventDeclaration, newNode, cancellationToken));
                }

                case SyntaxKind.EventFieldDeclaration:
                {
                    var eventDeclaration = (EventFieldDeclarationSyntax)memberDeclaration;

                    VariableDeclarationSyntax declaration = eventDeclaration.Declaration;

                    EventFieldDeclarationSyntax newNode = eventDeclaration.WithDeclaration(declaration.WithType(newType.WithTriviaFrom(declaration.Type)));

                    return(document.ReplaceNodeAsync(eventDeclaration, newNode, cancellationToken));
                }

                default:
                {
                    Debug.Fail(memberDeclaration.Kind().ToString());
                    return(Task.FromResult(document));
                }
                }
            }
        }
        public static async Task <Document> RefactorAsync(
            Document document,
            MemberDeclarationSyntax memberDeclaration,
            ITypeSymbol typeSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            TypeSyntax newType = typeSymbol.ToMinimalTypeSyntax(semanticModel, memberDeclaration.SpanStart);

            switch (memberDeclaration.Kind())
            {
            case SyntaxKind.MethodDeclaration:
            {
                var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration;

                MethodDeclarationSyntax newNode = methodDeclaration.WithReturnType(newType.WithTriviaFrom(methodDeclaration.ReturnType));

                return(await document.ReplaceNodeAsync(methodDeclaration, newNode, cancellationToken).ConfigureAwait(false));
            }

            case SyntaxKind.PropertyDeclaration:
            {
                var propertyDeclaration = (PropertyDeclarationSyntax)memberDeclaration;

                PropertyDeclarationSyntax newNode = propertyDeclaration.WithType(newType.WithTriviaFrom(propertyDeclaration.Type));

                return(await document.ReplaceNodeAsync(propertyDeclaration, newNode, cancellationToken).ConfigureAwait(false));
            }

            case SyntaxKind.IndexerDeclaration:
            {
                var indexerDeclaration = (IndexerDeclarationSyntax)memberDeclaration;

                IndexerDeclarationSyntax newNode = indexerDeclaration.WithType(newType.WithTriviaFrom(indexerDeclaration.Type));

                return(await document.ReplaceNodeAsync(indexerDeclaration, newNode, cancellationToken).ConfigureAwait(false));
            }

            case SyntaxKind.EventDeclaration:
            {
                var eventDeclaration = (EventDeclarationSyntax)memberDeclaration;

                EventDeclarationSyntax newNode = eventDeclaration.WithType(newType.WithTriviaFrom(eventDeclaration.Type));

                return(await document.ReplaceNodeAsync(eventDeclaration, newNode, cancellationToken).ConfigureAwait(false));
            }

            case SyntaxKind.EventFieldDeclaration:
            {
                var eventDeclaration = (EventFieldDeclarationSyntax)memberDeclaration;

                VariableDeclarationSyntax declaration = eventDeclaration.Declaration;
                VariableDeclaratorSyntax  declarator  = declaration.Variables.First();

                EventFieldDeclarationSyntax newNode = eventDeclaration.WithDeclaration(declaration.WithType(newType.WithTriviaFrom(declaration.Type)));

                return(await document.ReplaceNodeAsync(eventDeclaration, newNode, cancellationToken).ConfigureAwait(false));
            }

            default:
            {
                Debug.Fail(memberDeclaration.Kind().ToString());
                return(document);
            }
            }
        }
Esempio n. 21
0
        private static async Task <SyntaxNode> ReplaceNodeAndUpdateVariableTypeAsync(Document document, SyntaxNode root, SyntaxNode originalNode, SyntaxNode newNode, TypeSyntax newType, CancellationToken cancellationToken)
        {
            // Check if the original node was the value being
            // assigned to the variable in a variable declaration.
            if (originalNode.Parent is EqualsValueClauseSyntax equalsSyntax)
            {
                if (IsDeclaratorForObject(equalsSyntax.Parent, out VariableDeclarationSyntax declaration))
                {
                    // The original node is being assigned to a variable
                    // of type `object`. Change the type of the variable
                    // and replace the original node with the new node.
                    return(root.ReplaceNode(
                               declaration,
                               declaration.ReplaceNode(originalNode, newNode).WithType(newType.WithTriviaFrom(declaration.Type))
                               ));
                }
            }
            else
            {
                // Check if the node is being assigned to something.
                if ((originalNode.Parent is AssignmentExpressionSyntax assignment) && (assignment.Left is IdentifierNameSyntax identifier))
                {
                    // If it's being assigned to a local variable or a field in the same
                    // document, then we will try to change the type of that variable or field.
                    SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken);

                    SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(identifier);
                    if (symbolInfo.Symbol?.DeclaringSyntaxReferences.Length == 1)
                    {
                        VariableDeclarationSyntax?originalDeclaration = null;
                        VariableDeclarationSyntax?newDeclaration      = null;

                        switch (symbolInfo.Symbol.Kind)
                        {
                        case SymbolKind.Local:
                            if (IsDeclaratorForObject(symbolInfo.Symbol.DeclaringSyntaxReferences[0].GetSyntax(), out originalDeclaration))
                            {
                                newDeclaration = originalDeclaration.WithType(newType.WithTriviaFrom(originalDeclaration.Type));
                            }
                            break;

                        case SymbolKind.Field:
                            SyntaxNode fieldSyntax = symbolInfo.Symbol.DeclaringSyntaxReferences[0].GetSyntax();
                            // We can only change the type of the field if it's in the
                            // same document that we're replacing the original node in.
                            if (ReferenceEquals(fieldSyntax.SyntaxTree, originalNode.SyntaxTree))
                            {
                                if (IsDeclaratorForObject(fieldSyntax, out originalDeclaration))
                                {
                                    newDeclaration = originalDeclaration.WithType(newType.WithTriviaFrom(originalDeclaration.Type));
                                }
                            }
                            break;
                        }

                        // If a declaration was found, then replace the original node
                        // with the new node, and replace the original declaration with
                        // the new declaration that will change the type of the variable.
                        if (originalDeclaration is not null && newDeclaration is not null)
                        {
                            return(root.ReplaceNodes(
                                       new[] { originalNode, originalDeclaration },
                                       (node, _) => (node == originalNode) ? newNode : newDeclaration
                                       ));
                        }
                    }
                }
            }

            // If we get to this point, then the original node is not part
            // of a statement that requires us to update any variable types,
            // so just replace the original node with the new node.
            return(root.ReplaceNode(originalNode, newNode));
        }