private static AddExceptionToDocumentationCommentAnalysis Analyze(
            SyntaxNode node,
            ExpressionSyntax expression,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            var exceptionSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken) as INamedTypeSymbol;

            if (exceptionSymbol?.InheritsFromException(semanticModel) == true)
            {
                ISymbol declarationSymbol = GetDeclarationSymbol(node.SpanStart, semanticModel, cancellationToken);

                if (declarationSymbol?.GetSyntax(cancellationToken) is MemberDeclarationSyntax containingMember)
                {
                    DocumentationCommentTriviaSyntax comment = containingMember.GetSingleLineDocumentationComment();

                    if (comment != null &&
                        CanAddExceptionToComment(comment, exceptionSymbol, semanticModel, cancellationToken))
                    {
                        ThrowInfo throwInfo = ThrowInfo.Create(node, exceptionSymbol, declarationSymbol);

                        return(new AddExceptionToDocumentationCommentAnalysis(throwInfo, comment.ParentTrivia));
                    }
                }
            }

            return(AddExceptionToDocumentationCommentAnalysis.NoSuccess);
        }
        private static ThrowInfo GetUndocumentedExceptionInfo(
            SyntaxNode node,
            ExpressionSyntax expression,
            MemberDeclarationSyntax declaration,
            ISymbol declarationSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (expression != null)
            {
                var typeSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken) as INamedTypeSymbol;

                if (typeSymbol?.InheritsFromException(semanticModel) == true)
                {
                    DocumentationCommentTriviaSyntax comment = declaration.GetSingleLineDocumentationComment();

                    if (comment != null &&
                        CanAddExceptionToComment(comment, typeSymbol, semanticModel, cancellationToken))
                    {
                        return(ThrowInfo.Create(node, typeSymbol, declarationSymbol));
                    }
                }
            }

            return(null);
        }
        private static async Task <Document> RefactorAsync(
            Document document,
            SyntaxNode node,
            ExpressionSyntax expression,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            ITypeSymbol exceptionSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken);

            ISymbol declarationSymbol = GetDeclarationSymbol(node.SpanStart, semanticModel, cancellationToken);

            var memberDeclaration = await declarationSymbol
                                    .DeclaringSyntaxReferences[0]
                                    .GetSyntaxAsync(cancellationToken)
                                    .ConfigureAwait(false) as MemberDeclarationSyntax;

            SyntaxTrivia trivia = memberDeclaration.GetSingleLineDocumentationCommentTrivia();

            ThrowInfo throwInfo = ThrowInfo.Create(node, exceptionSymbol, declarationSymbol);

            return(await RefactorAsync(
                       document,
                       trivia,
                       throwInfo,
                       memberDeclaration,
                       declarationSymbol,
                       semanticModel,
                       cancellationToken).ConfigureAwait(false));
        }
        private static ThrowInfo GetUndocumentedExceptionInfo(
            SyntaxNode node,
            ExpressionSyntax expression,
            MemberDeclarationSyntax declaration,
            ISymbol declarationSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (expression != null)
            {
                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken);

                if (typeSymbol?.IsErrorType() == false &&
                    SymbolUtility.IsException(typeSymbol, semanticModel))
                {
                    DocumentationCommentTriviaSyntax comment = declaration.GetSingleLineDocumentationComment();

                    if (comment != null &&
                        !ContainsException(comment, typeSymbol, semanticModel, cancellationToken))
                    {
                        return(ThrowInfo.Create(node, typeSymbol, declarationSymbol));
                    }
                }
            }

            return(null);
        }
        private static ThrowInfo GetUndocumentedExceptionInfo(
            SyntaxNode node,
            ExpressionSyntax expression,
            MemberDeclarationSyntax containingMember,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (expression != null)
            {
                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken);

                if (typeSymbol?.IsErrorType() == false &&
                    Symbol.IsException(typeSymbol, semanticModel))
                {
                    SyntaxTrivia trivia = containingMember.GetSingleLineDocumentationComment();

                    if (trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia))
                    {
                        var comment = trivia.GetStructure() as DocumentationCommentTriviaSyntax;

                        if (comment?.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia) == true &&
                            !ContainsException(comment, typeSymbol, semanticModel, cancellationToken))
                        {
                            return(ThrowInfo.Create(node, typeSymbol));
                        }
                    }
                }
            }

            return(null);
        }
        private static async Task ComputeRefactoringAsync(RefactoringContext context, SyntaxNode node, ExpressionSyntax expression)
        {
            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

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

            if (exceptionSymbol?.IsErrorType() == false &&
                Symbol.IsException(exceptionSymbol, semanticModel))
            {
                ISymbol declarationSymbol = GetDeclarationSymbol(node.SpanStart, semanticModel, context.CancellationToken);

                if (declarationSymbol != null)
                {
                    var containingMember = await declarationSymbol
                                           .DeclaringSyntaxReferences[0]
                                           .GetSyntaxAsync(context.CancellationToken)
                                           .ConfigureAwait(false) as MemberDeclarationSyntax;

                    if (containingMember != null)
                    {
                        SyntaxTrivia trivia = containingMember.GetSingleLineDocumentationComment();

                        if (trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia))
                        {
                            var comment = trivia.GetStructure() as DocumentationCommentTriviaSyntax;

                            if (comment?.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia) == true &&
                                !ContainsException(comment, exceptionSymbol, semanticModel, context.CancellationToken))
                            {
                                ThrowInfo throwInfo1 = ThrowInfo.Create(node, exceptionSymbol);

                                IParameterSymbol parameterSymbol = throwInfo1.GetParameterSymbol(declarationSymbol, semanticModel, context.CancellationToken);

                                context.RegisterRefactoring(
                                    "Add exception to documentation comment",
                                    cancellationToken => RefactorAsync(context.Document, trivia, exceptionSymbol, parameterSymbol, cancellationToken));

                                foreach (ThrowInfo throwInfo2 in GetOtherUndocumentedExceptions(containingMember, f => node != f, semanticModel, context.CancellationToken))
                                {
                                    if (throwInfo2.ExceptionSymbol != exceptionSymbol)
                                    {
                                        var infos = new List <ThrowInfo>();
                                        infos.Add(throwInfo1);
                                        infos.Add(throwInfo2);

                                        context.RegisterRefactoring(
                                            "Add all exceptions to documentation comment",
                                            cancellationToken => RefactorAsync(context.Document, infos, containingMember, declarationSymbol, trivia, cancellationToken));

                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        private static IEnumerable <ThrowInfo> GetOtherUndocumentedExceptions(
            MemberDeclarationSyntax declaration,
            ISymbol declarationSymbol,
            Func <SyntaxNode, bool> predicate,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            foreach (SyntaxNode node in declaration.DescendantNodes(f => !f.IsKind(
                                                                        SyntaxKind.AnonymousMethodExpression,
                                                                        SyntaxKind.SimpleLambdaExpression,
                                                                        SyntaxKind.ParenthesizedLambdaExpression)))
            {
                switch (node.Kind())
                {
                case SyntaxKind.ThrowStatement:
                {
                    if (predicate(node))
                    {
                        var throwStatement = (ThrowStatementSyntax)node;

                        ThrowInfo info = GetUndocumentedExceptionInfo(node, throwStatement.Expression, declaration, declarationSymbol, semanticModel, cancellationToken);

                        if (info != null)
                        {
                            yield return(info);
                        }
                    }

                    break;
                }

                case SyntaxKind.ThrowExpression:
                {
                    if (predicate(node))
                    {
                        var       throwExpression = (ThrowExpressionSyntax)node;
                        ThrowInfo info            = GetUndocumentedExceptionInfo(node, throwExpression.Expression, declaration, declarationSymbol, semanticModel, cancellationToken);

                        if (info != null)
                        {
                            yield return(info);
                        }
                    }

                    break;
                }
                }
            }
        }
Example #8
0
        private static IEnumerable <ThrowInfo> GetOtherUndocumentedExceptions(
            MemberDeclarationSyntax declaration,
            ISymbol declarationSymbol,
            Func <SyntaxNode, bool> predicate,
            INamedTypeSymbol exceptionSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            foreach (SyntaxNode node in declaration.DescendantNodes(f => !CSharpFacts.IsAnonymousFunctionExpression(f.Kind())))
            {
                switch (node.Kind())
                {
                case SyntaxKind.ThrowStatement:
                {
                    if (predicate(node))
                    {
                        var throwStatement = (ThrowStatementSyntax)node;

                        ThrowInfo info = GetUndocumentedExceptionInfo(node, throwStatement.Expression, declaration, declarationSymbol, exceptionSymbol, semanticModel, cancellationToken);

                        if (info != null)
                        {
                            yield return(info);
                        }
                    }

                    break;
                }

                case SyntaxKind.ThrowExpression:
                {
                    if (predicate(node))
                    {
                        var       throwExpression = (ThrowExpressionSyntax)node;
                        ThrowInfo info            = GetUndocumentedExceptionInfo(node, throwExpression.Expression, declaration, declarationSymbol, exceptionSymbol, semanticModel, cancellationToken);

                        if (info != null)
                        {
                            yield return(info);
                        }
                    }

                    break;
                }
                }
            }
        }
Example #9
0
        private static async Task <Document> RefactorAsync(
            Document document,
            SyntaxTrivia trivia,
            ThrowInfo throwInfo,
            MemberDeclarationSyntax memberDeclaration,
            ISymbol declarationSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            SourceText sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            var throwInfos = new List <ThrowInfo>()
            {
                throwInfo
            };

            INamedTypeSymbol exceptionSymbol = semanticModel.GetTypeByMetadataName("System.Exception");

            foreach (ThrowInfo info in GetOtherUndocumentedExceptions(memberDeclaration, declarationSymbol, node => node != throwInfo.Node, exceptionSymbol, semanticModel, cancellationToken))
            {
                if (!throwInfos.Any(f => f.ExceptionSymbol == info.ExceptionSymbol))
                {
                    throwInfos.Add(info);
                }
            }

            string indent = GetIndent(memberDeclaration.GetLeadingTrivia());

            StringBuilder sb = StringBuilderCache.GetInstance();

            foreach (ThrowInfo info in throwInfos)
            {
                sb.Append(indent);

                IParameterSymbol parameterSymbol = info.GetParameterSymbol(semanticModel, cancellationToken);

                AppendExceptionDocumentation(trivia, info.ExceptionSymbol, parameterSymbol, semanticModel, ref sb);
            }

            string newText = StringBuilderCache.GetStringAndFree(sb);

            var textChange = new TextChange(new TextSpan(trivia.FullSpan.End, 0), newText);

            SourceText newSourceText = sourceText.WithChanges(textChange);

            return(document.WithText(newSourceText));
        }
        private static IEnumerable <ThrowInfo> GetOtherUndocumentedExceptions(
            MemberDeclarationSyntax containingMember,
            Func <SyntaxNode, bool> predicate,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            foreach (SyntaxNode descendant in containingMember.DescendantNodes())
            {
                switch (descendant.Kind())
                {
                case SyntaxKind.ThrowStatement:
                {
                    if (predicate(descendant))
                    {
                        var throwStatement = (ThrowStatementSyntax)descendant;

                        ThrowInfo info = GetUndocumentedExceptionInfo(descendant, throwStatement.Expression, containingMember, semanticModel, cancellationToken);

                        if (info != null)
                        {
                            yield return(info);
                        }
                    }

                    break;
                }

                case SyntaxKind.ThrowExpression:
                {
                    if (predicate(descendant))
                    {
                        var       throwExpression = (ThrowExpressionSyntax)descendant;
                        ThrowInfo info            = GetUndocumentedExceptionInfo(descendant, throwExpression.Expression, containingMember, semanticModel, cancellationToken);

                        if (info != null)
                        {
                            yield return(info);
                        }
                    }

                    break;
                }
                }
            }
        }
Example #11
0
        private static Task <Document> RefactorAsync(
            Document document,
            SyntaxTrivia trivia,
            ThrowInfo throwInfo,
            MemberDeclarationSyntax memberDeclaration,
            ISymbol declarationSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            var throwInfos = new List <ThrowInfo>()
            {
                throwInfo
            };

            INamedTypeSymbol exceptionSymbol = semanticModel.GetTypeByMetadataName("System.Exception");

            foreach (ThrowInfo info in GetOtherUndocumentedExceptions(memberDeclaration, declarationSymbol, node => node != throwInfo.Node, exceptionSymbol, semanticModel, cancellationToken))
            {
                if (!throwInfos.Any(f => SymbolEqualityComparer.Default.Equals(f.ExceptionSymbol, info.ExceptionSymbol)))
                {
                    throwInfos.Add(info);
                }
            }

            string indent = GetIndent(memberDeclaration.GetLeadingTrivia());

            StringBuilder sb = StringBuilderCache.GetInstance();

            foreach (ThrowInfo info in throwInfos)
            {
                sb.Append(indent);

                IParameterSymbol parameterSymbol = info.GetParameterSymbol(semanticModel, cancellationToken);

                AppendExceptionDocumentation(trivia, info.ExceptionSymbol, parameterSymbol, semanticModel, ref sb);
            }

            return(document.WithTextChangeAsync(
                       new TextSpan(trivia.FullSpan.End, 0),
                       StringBuilderCache.GetStringAndFree(sb),
                       cancellationToken));
        }
        private static async Task <Document> RefactorAsync(
            Document document,
            SyntaxTrivia trivia,
            ThrowInfo throwInfo,
            MemberDeclarationSyntax memberDeclaration,
            ISymbol declarationSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            SourceText sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            var throwInfos = new List <ThrowInfo>();

            throwInfos.Add(throwInfo);

            foreach (ThrowInfo info in GetOtherUndocumentedExceptions(memberDeclaration, declarationSymbol, node => node != throwInfo.Node, semanticModel, cancellationToken))
            {
                if (!throwInfos.Any(f => f.ExceptionSymbol == info.ExceptionSymbol))
                {
                    throwInfos.Add(info);
                }
            }

            string indent = GetIndent(trivia, sourceText, cancellationToken);

            var sb = new StringBuilder();

            foreach (ThrowInfo info in throwInfos)
            {
                sb.Append(indent);

                IParameterSymbol parameterSymbol = info.GetParameterSymbol(semanticModel, cancellationToken);

                AppendExceptionDocumentation(trivia, info.ExceptionSymbol, parameterSymbol, semanticModel, ref sb);
            }

            var textChange = new TextChange(new TextSpan(trivia.FullSpan.End, 0), sb.ToString());

            SourceText newSourceText = sourceText.WithChanges(textChange);

            return(document.WithText(newSourceText));
        }
        private static AddExceptionToDocumentationCommentAnalysis Analyze(
            SyntaxNode node,
            ExpressionSyntax expression,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            ITypeSymbol exceptionSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken);

            if (exceptionSymbol?.IsErrorType() == false &&
                SymbolUtility.IsException(exceptionSymbol, semanticModel))
            {
                ISymbol declarationSymbol = GetDeclarationSymbol(node.SpanStart, semanticModel, cancellationToken);

                if (declarationSymbol != null)
                {
                    var containingMember = declarationSymbol
                                           .DeclaringSyntaxReferences[0]
                                           .GetSyntax(cancellationToken) as MemberDeclarationSyntax;

                    if (containingMember != null)
                    {
                        SyntaxTrivia trivia = containingMember.GetSingleLineDocumentationComment();

                        if (trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia))
                        {
                            var comment = trivia.GetStructure() as DocumentationCommentTriviaSyntax;

                            if (comment?.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia) == true &&
                                !ContainsException(comment, exceptionSymbol, semanticModel, cancellationToken))
                            {
                                ThrowInfo throwInfo = ThrowInfo.Create(node, exceptionSymbol, declarationSymbol);

                                return(new AddExceptionToDocumentationCommentAnalysis(throwInfo, trivia));
                            }
                        }
                    }
                }
            }

            return(AddExceptionToDocumentationCommentAnalysis.NoSuccess);
        }
Example #14
0
        private static ThrowInfo GetUndocumentedExceptionInfo(
            SyntaxNode node,
            ExpressionSyntax expression,
            MemberDeclarationSyntax declaration,
            ISymbol declarationSymbol,
            INamedTypeSymbol exceptionSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (expression == null)
            {
                return(null);
            }

            if (semanticModel.GetTypeSymbol(expression, cancellationToken) is not INamedTypeSymbol typeSymbol)
            {
                return(null);
            }

            if (!InheritsFromException(typeSymbol, exceptionSymbol))
            {
                return(null);
            }

            DocumentationCommentTriviaSyntax comment = declaration.GetSingleLineDocumentationComment();

            if (comment == null)
            {
                return(null);
            }

            if (!CanAddExceptionToComment(comment, typeSymbol, semanticModel, cancellationToken))
            {
                return(null);
            }

            return(ThrowInfo.Create(node, typeSymbol, declarationSymbol));
        }
 public IParameterSymbol GetParameterSymbol(
     SemanticModel semanticModel,
     CancellationToken cancellationToken)
 {
     return(ThrowInfo?.GetParameterSymbol(semanticModel, cancellationToken));
 }
 internal AddExceptionToDocumentationCommentAnalysis(ThrowInfo info, SyntaxTrivia documentationComment)
 {
     ThrowInfo            = info;
     DocumentationComment = documentationComment;
 }