예제 #1
0
        private void ReportNoExceptionDiagnostics(SyntaxNodeAnalysisContext context, SyntaxNode node, DocumentationCommentTriviaSyntax xmlTrivia)
        {
            var exceptionCommentNames = xmlTrivia.DescendantNodes().OfType <XmlNameAttributeSyntax>()
                                        .Where(attribute => IsNameAttribute(attribute, exceptionTag))
                                        .Select(attribute => attribute.Identifier.ToString());

            var exceptionTokens = GetExceptionTokens(node);

            foreach (var exceptionToken in exceptionTokens)
            {
                var exceptionName = exceptionToken.Text;

                if (!exceptionCommentNames.Any(commentName => commentName.Equals(exceptionName)))
                {
                    context.ReportDiagnostic(Diagnostic.Create(NoExceptionRule, exceptionToken.GetLocation(), exceptionToken.Text));
                }
            }
        }
예제 #2
0
        private void ReportNoParamDiagnostics(SyntaxNodeAnalysisContext context, BaseMethodDeclarationSyntax node, DocumentationCommentTriviaSyntax xmlTrivia)
        {
            var paramCommentNames = xmlTrivia.DescendantNodes().OfType <XmlNameAttributeSyntax>()
                                    .Where(attribute => IsNameAttribute(attribute, paramTag))
                                    .Select(attribute => attribute.Identifier.ToString());

            foreach (var parameter in node.ParameterList.Parameters)
            {
                var paramName = parameter.Identifier.Text;

                if (HasThisModifier(parameter))
                {
                    continue;
                }

                if (!paramCommentNames.Any(commentName => commentName.Equals(paramName)))
                {
                    context.ReportDiagnostic(Diagnostic.Create(NoParamRule, parameter.Identifier.GetLocation(), parameter.Identifier.Text));
                }
            }
        }
        private async Task <Document> CreateChangedDocumentAsync(CodeFixContext context, DocumentationCommentTriviaSyntax documentationCommentTriviaSyntax, CancellationToken cancellationToken)
        {
            StringBuilder leadingTriviaBuilder      = new StringBuilder();
            SyntaxToken   parentToken               = documentationCommentTriviaSyntax.ParentTrivia.Token;
            int           documentationCommentIndex = parentToken.LeadingTrivia.IndexOf(documentationCommentTriviaSyntax.ParentTrivia);

            for (int i = 0; i < documentationCommentIndex; i++)
            {
                SyntaxTrivia trivia = parentToken.LeadingTrivia[i];
                switch (trivia.Kind())
                {
                case SyntaxKind.EndOfLineTrivia:
                    leadingTriviaBuilder.Clear();
                    break;

                case SyntaxKind.WhitespaceTrivia:
                    leadingTriviaBuilder.Append(trivia.ToFullString());
                    break;

                default:
                    break;
                }
            }

            leadingTriviaBuilder.Append(documentationCommentTriviaSyntax.GetLeadingTrivia().ToFullString());

            // this is the trivia that should appear at the beginning of each line of the comment.
            SyntaxTrivia leadingTrivia = SyntaxFactory.DocumentationCommentExterior(leadingTriviaBuilder.ToString());

            string newLineText   = context.Document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp);
            var    semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken);

            var documentedSymbol = semanticModel.GetDeclaredSymbol(parentToken.Parent.FirstAncestorOrSelf <SyntaxNode>(SyntaxNodeExtensionsEx.IsSymbolDeclaration), context.CancellationToken);

            DocumentationCommentTriviaSyntax contentsOnly = RemoveExteriorTrivia(documentationCommentTriviaSyntax);

            contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.ChildNodes(), (originalNode, rewrittenNode) => RenderBlockElementAsMarkdown(originalNode, rewrittenNode, newLineText, documentedSymbol));
            string renderedContent = contentsOnly.Content.ToFullString();

            string[] lines = renderedContent.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
            SyntaxList <XmlNodeSyntax> newContent = XmlSyntaxFactory.List();

            for (int i = 0; i < lines.Length; i++)
            {
                string line = lines[i];
                if (string.IsNullOrWhiteSpace(line))
                {
                    if (i == lines.Length - 1)
                    {
                        break;
                    }

                    line = string.Empty;
                }

                if (newContent.Count > 0)
                {
                    newContent = newContent.Add(XmlSyntaxFactory.NewLine(newLineText).WithTrailingTrivia(SyntaxFactory.DocumentationCommentExterior("///")));
                }

                newContent = newContent.Add(XmlSyntaxFactory.Text(line.TrimEnd(), xmlEscape: false));
            }

            contentsOnly = contentsOnly.WithContent(newContent);
            contentsOnly =
                contentsOnly
                .ReplaceExteriorTrivia(leadingTrivia)
                .WithLeadingTrivia(SyntaxFactory.DocumentationCommentExterior("///"))
                .WithTrailingTrivia(SyntaxFactory.EndOfLine(Environment.NewLine));

            string           fullContent         = contentsOnly.ToFullString();
            SyntaxTriviaList parsedTrivia        = SyntaxFactory.ParseLeadingTrivia(fullContent);
            SyntaxTrivia     documentationTrivia = parsedTrivia.FirstOrDefault(i => i.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia));

            contentsOnly = documentationTrivia.GetStructure() as DocumentationCommentTriviaSyntax;
            if (contentsOnly == null)
            {
                return(context.Document);
            }

            // Remove unnecessary nested paragraph elements
            contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.DescendantNodes().OfType <XmlElementSyntax>(), MarkUnnecessaryParagraphs);
            contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.DescendantNodes().OfType <XmlElementSyntax>(), RemoveUnnecessaryParagraphs);

            SyntaxNode root = await context.Document.GetSyntaxRootAsync(cancellationToken);

            SyntaxNode newRoot = root.ReplaceNode(documentationCommentTriviaSyntax, contentsOnly);

            if (documentationCommentTriviaSyntax.IsEquivalentTo(contentsOnly))
            {
                return(context.Document);
            }

            if (documentationCommentTriviaSyntax.ToFullString().Equals(contentsOnly.ToFullString(), StringComparison.Ordinal))
            {
                return(context.Document);
            }

            return(context.Document.WithSyntaxRoot(newRoot));
        }
예제 #4
0
 private bool HasXmlNameTag(DocumentationCommentTriviaSyntax xmlTrivia, string name)
 {
     return(xmlTrivia.DescendantNodes().OfType <XmlElementStartTagSyntax>()
            .Any(node => node.Name.ToString().Equals(name)));
 }