Exemplo n.º 1
0
        public override TDeclarationNode AddParameters <TDeclarationNode>(
            TDeclarationNode destination,
            IEnumerable <IParameterSymbol> parameters,
            CSharpCodeGenerationOptions options,
            CancellationToken cancellationToken)
        {
            var currentParameterList = destination.GetParameterList();

            var parameterCount = currentParameterList != null ? currentParameterList.Parameters.Count : 0;
            var seenOptional   = currentParameterList != null && parameterCount > 0 && currentParameterList.Parameters[^ 1].Default != null;
            var isFirstParam   = parameterCount == 0;

            var editor = new SyntaxEditor(destination, CSharpSyntaxGenerator.Instance);

            foreach (var parameter in parameters)
            {
                var parameterSyntax = ParameterGenerator.GetParameter(parameter, options, isExplicit: false, isFirstParam: isFirstParam, seenOptional: seenOptional);

                AddParameterEditor.AddParameter(
                    CSharpSyntaxFacts.Instance,
                    editor,
                    destination,
                    parameterCount,
                    parameterSyntax,
                    cancellationToken);

                parameterCount++;
                isFirstParam = false;
                seenOptional = seenOptional || parameterSyntax.Default != null;
            }

            var finalMember = editor.GetChangedRoot();

            return(Cast <TDeclarationNode>(finalMember));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Adds a parameter to a method.
        /// </summary>
        /// <param name="newParameterIndex"><see langword="null"/> to add as the final parameter</param>
        /// <returns></returns>
        public static async Task <Solution> AddParameterAsync(
            Document invocationDocument,
            IMethodSymbol method,
            ITypeSymbol newParameterType,
            RefKind refKind,
            string parameterName,
            int?newParameterIndex,
            bool fixAllReferences,
            CancellationToken cancellationToken)
        {
            var solution = invocationDocument.Project.Solution;

            var referencedSymbols = fixAllReferences
                ? await FindMethodDeclarationReferencesAsync(invocationDocument, method, cancellationToken).ConfigureAwait(false)
                : method.GetAllMethodSymbolsOfPartialParts();

            var anySymbolReferencesNotInSource = referencedSymbols.Any(symbol => !symbol.IsFromSource());
            var locationsInSource = referencedSymbols.Where(symbol => symbol.IsFromSource());

            // Indexing Locations[0] is valid because IMethodSymbols have one location at most
            // and IsFromSource() tests if there is at least one location.
            var locationsByDocument = locationsInSource.ToLookup(declarationLocation
                                                                 => solution.GetRequiredDocument(declarationLocation.Locations[0].SourceTree !));

            foreach (var documentLookup in locationsByDocument)
            {
                var document    = documentLookup.Key;
                var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>();
                var syntaxRoot  = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var editor    = new SyntaxEditor(syntaxRoot, solution.Workspace.Services);
                var generator = editor.Generator;
                foreach (var methodDeclaration in documentLookup)
                {
                    var methodNode         = syntaxRoot.FindNode(methodDeclaration.Locations[0].SourceSpan, getInnermostNodeForTie: true);
                    var existingParameters = generator.GetParameters(methodNode);
                    var insertionIndex     = newParameterIndex ?? existingParameters.Count;

                    // if the preceding parameter is optional, the new parameter must also be optional
                    // see also BC30202 and CS1737
                    var parameterMustBeOptional = insertionIndex > 0 &&
                                                  syntaxFacts.GetDefaultOfParameter(existingParameters[insertionIndex - 1]) != null;

                    var parameterSymbol = CreateParameterSymbol(
                        methodDeclaration, newParameterType, refKind, parameterMustBeOptional, parameterName);

                    var argumentInitializer  = parameterMustBeOptional ? generator.DefaultExpression(newParameterType) : null;
                    var parameterDeclaration = generator.ParameterDeclaration(parameterSymbol, argumentInitializer)
                                               .WithAdditionalAnnotations(Formatter.Annotation);
                    if (anySymbolReferencesNotInSource && methodDeclaration == method)
                    {
                        parameterDeclaration = parameterDeclaration.WithAdditionalAnnotations(
                            ConflictAnnotation.Create(FeaturesResources.Related_method_signatures_found_in_metadata_will_not_be_updated));
                    }

                    if (method.MethodKind == MethodKind.ReducedExtension && insertionIndex < existingParameters.Count)
                    {
                        insertionIndex++;
                    }

                    AddParameterEditor.AddParameter(syntaxFacts, editor, methodNode, insertionIndex, parameterDeclaration, cancellationToken);
                }

                var newRoot = editor.GetChangedRoot();
                solution = solution.WithDocumentSyntaxRoot(document.Id, newRoot);
            }

            return(solution);
        }