コード例 #1
0
        private static XmlEmptyElementSyntax BuildSeeElement(SyntaxToken identifier, TypeParameterListSyntax typeParameters)
        {
            TypeSyntax identifierName;

            // Get a TypeSyntax representing the class name with its type parameters
            if (typeParameters == null || !typeParameters.Parameters.Any())
            {
                identifierName = SyntaxFactory.IdentifierName(identifier.WithoutTrivia());
            }
            else
            {
                identifierName = SyntaxFactory.GenericName(identifier.WithoutTrivia(), ParameterToArgumentListSyntax(typeParameters));
            }

            return(XmlSyntaxFactory.SeeElement(SyntaxFactory.TypeCref(identifierName)));
        }
コード例 #2
0
        private static SyntaxList <XmlNodeSyntax> BuildStandardText(SyntaxToken identifier, TypeParameterListSyntax typeParameters, string newLineText, string preText, string postText)
        {
            TypeSyntax identifierName;

            // Get a TypeSyntax representing the class name with its type parameters
            if (typeParameters == null || !typeParameters.Parameters.Any())
            {
                identifierName = SyntaxFactory.IdentifierName(identifier.WithoutTrivia());
            }
            else
            {
                identifierName = SyntaxFactory.GenericName(identifier.WithoutTrivia(), ParameterToArgumentListSyntax(typeParameters));
            }

            return(XmlSyntaxFactory.List(
                       XmlSyntaxFactory.NewLine(newLineText),
                       XmlSyntaxFactory.Text(preText),
                       XmlSyntaxFactory.SeeElement(SyntaxFactory.TypeCref(identifierName)),
                       XmlSyntaxFactory.Text(postText.EndsWith(".") ? postText : (postText + "."))));
        }
コード例 #3
0
        private static async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var documentRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            SyntaxNode syntax = documentRoot.FindNode(diagnostic.Location.SourceSpan);

            if (syntax == null)
            {
                return(document);
            }

            MethodDeclarationSyntax   methodDeclarationSyntax   = syntax.FirstAncestorOrSelf <MethodDeclarationSyntax>();
            DelegateDeclarationSyntax delegateDeclarationSyntax = syntax.FirstAncestorOrSelf <DelegateDeclarationSyntax>();

            if (methodDeclarationSyntax == null && delegateDeclarationSyntax == null)
            {
                return(document);
            }

            DocumentationCommentTriviaSyntax documentationComment =
                methodDeclarationSyntax?.GetDocumentationCommentTriviaSyntax()
                ?? delegateDeclarationSyntax?.GetDocumentationCommentTriviaSyntax();

            if (documentationComment == null)
            {
                return(document);
            }

            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            bool isTask;
            bool isAsynchronousTestMethod;

            if (methodDeclarationSyntax != null)
            {
                isTask = IsTaskReturningMethod(semanticModel, methodDeclarationSyntax, cancellationToken);
                isAsynchronousTestMethod = isTask && IsAsynchronousTestMethod(semanticModel, methodDeclarationSyntax, cancellationToken);
            }
            else
            {
                isTask = IsTaskReturningMethod(semanticModel, delegateDeclarationSyntax, cancellationToken);
                isAsynchronousTestMethod = false;
            }

            XmlNodeSyntax returnsElement = documentationComment.Content.GetFirstXmlElement(XmlCommentHelper.ReturnsXmlTag) as XmlNodeSyntax;

            if (returnsElement != null && !isTask)
            {
                // This code fix doesn't know how to do anything more than document Task-returning methods.
                return(document);
            }

            SyntaxList <XmlNodeSyntax> content = XmlSyntaxFactory.List();

            if (isTask)
            {
                content = content.Add(XmlSyntaxFactory.Text("A "));
                content = content.Add(XmlSyntaxFactory.SeeElement(SyntaxFactory.TypeCref(SyntaxFactory.ParseTypeName("global::System.Threading.Tasks.Task"))).WithAdditionalAnnotations(Simplifier.Annotation));
                string operationKind = isAsynchronousTestMethod ? "unit test" : "operation";
                content = content.Add(XmlSyntaxFactory.Text($" representing the asynchronous {operationKind}."));

                // wrap the generated content in a <placeholder> element for review.
                content = XmlSyntaxFactory.List(XmlSyntaxFactory.PlaceholderElement(content));
            }

            // Try to replace an existing <returns> element if the comment contains one. Otherwise, add it as a new element.
            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            SyntaxNode newRoot;

            if (returnsElement != null)
            {
                XmlEmptyElementSyntax emptyElement = returnsElement as XmlEmptyElementSyntax;
                if (emptyElement != null)
                {
                    XmlElementSyntax updatedReturns = XmlSyntaxFactory.Element(XmlCommentHelper.ReturnsXmlTag, content)
                                                      .WithLeadingTrivia(returnsElement.GetLeadingTrivia())
                                                      .WithTrailingTrivia(returnsElement.GetTrailingTrivia());
                    newRoot = root.ReplaceNode(returnsElement, updatedReturns);
                }
                else
                {
                    XmlElementSyntax updatedReturns = ((XmlElementSyntax)returnsElement).WithContent(content);
                    newRoot = root.ReplaceNode(returnsElement, updatedReturns);
                }
            }
            else
            {
                string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp);

                returnsElement = XmlSyntaxFactory.Element(XmlCommentHelper.ReturnsXmlTag, content);

                XmlNodeSyntax leadingNewLine = XmlSyntaxFactory.NewLine(newLineText);

                // HACK: The formatter isn't working when contents are added to an existing documentation comment, so we
                // manually apply the indentation from the last line of the existing comment to each new line of the
                // generated content.
                SyntaxTrivia exteriorTrivia = GetLastDocumentationCommentExteriorTrivia(documentationComment);
                if (!exteriorTrivia.Token.IsMissing)
                {
                    leadingNewLine = leadingNewLine.ReplaceExteriorTrivia(exteriorTrivia);
                    returnsElement = returnsElement.ReplaceExteriorTrivia(exteriorTrivia);
                }

                DocumentationCommentTriviaSyntax newDocumentationComment = documentationComment.WithContent(
                    documentationComment.Content.InsertRange(
                        documentationComment.Content.Count - 1,
                        XmlSyntaxFactory.List(leadingNewLine, returnsElement)));

                newRoot = root.ReplaceNode(documentationComment, newDocumentationComment);
            }

            return(document.WithSyntaxRoot(newRoot));
        }
コード例 #4
0
        private static Task <Document> GetMethodDocumentationTransformedDocumentAsync(Document document, SyntaxNode root, SemanticModel semanticModel, MethodDeclarationSyntax methodDeclaration, CancellationToken cancellationToken)
        {
            SyntaxTriviaList leadingTrivia = methodDeclaration.GetLeadingTrivia();
            int insertionIndex             = GetInsertionIndex(ref leadingTrivia);

            string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp);

            var documentationNodes = new List <XmlNodeSyntax>();

            documentationNodes.Add(XmlSyntaxFactory.SummaryElement(newLineText));

            if (methodDeclaration.TypeParameterList != null)
            {
                foreach (var typeParameter in methodDeclaration.TypeParameterList.Parameters)
                {
                    documentationNodes.Add(XmlSyntaxFactory.NewLine(newLineText));
                    documentationNodes.Add(XmlSyntaxFactory.TypeParamElement(typeParameter.Identifier.ValueText));
                }
            }

            if (methodDeclaration.ParameterList != null)
            {
                foreach (var parameter in methodDeclaration.ParameterList.Parameters)
                {
                    documentationNodes.Add(XmlSyntaxFactory.NewLine(newLineText));
                    documentationNodes.Add(XmlSyntaxFactory.ParamElement(parameter.Identifier.ValueText));
                }
            }

            TypeSyntax typeName;

            var typeSymbol = semanticModel.GetSymbolInfo(methodDeclaration.ReturnType, cancellationToken).Symbol as INamedTypeSymbol;

            if (typeSymbol.IsGenericType)
            {
                typeName = SyntaxFactory.ParseTypeName("global::System.Threading.Tasks.Task<TResult>");
            }
            else
            {
                typeName = SyntaxFactory.ParseTypeName("global::System.Threading.Tasks.Task");
            }

            XmlNodeSyntax[] returnContent =
            {
                XmlSyntaxFactory.Text(DocumentationResources.TaskReturnElementFirstPart),
                XmlSyntaxFactory.SeeElement(SyntaxFactory.TypeCref(typeName)).WithAdditionalAnnotations(Simplifier.Annotation),
                XmlSyntaxFactory.Text(DocumentationResources.TaskReturnElementSecondPart),
            };

            documentationNodes.Add(XmlSyntaxFactory.NewLine(newLineText));
            documentationNodes.Add(XmlSyntaxFactory.ReturnsElement(returnContent));

            var documentationComment =
                XmlSyntaxFactory.DocumentationComment(
                    newLineText,
                    documentationNodes.ToArray());
            var trivia = SyntaxFactory.Trivia(documentationComment);

            SyntaxTriviaList newLeadingTrivia = leadingTrivia.Insert(insertionIndex, trivia);
            SyntaxNode       newElement       = methodDeclaration.WithLeadingTrivia(newLeadingTrivia);

            return(Task.FromResult(document.WithSyntaxRoot(root.ReplaceNode(methodDeclaration, newElement))));
        }