Beispiel #1
0
        public override SyntaxNode VisitCatchClause(CatchClauseSyntax node)
        {
            if (!node.DescendantNodes().OfType <ThrowStatementSyntax>().Any())
            {
                BlockSyntax block = node.DescendantNodes().OfType <BlockSyntax>().Single();
                if (!block.Statements.Any())
                {
                    block = SyntaxFactory.Block(new StatementSyntax[] { SyntaxFactory.ThrowStatement() });

                    node = node.WithBlock(block);
                    return(node);
                }
            }
            return(base.VisitCatchClause(node));
        }
        public override SyntaxNode VisitCatchClause(CatchClauseSyntax node)
        {
            if(!node.DescendantNodes().OfType<ThrowStatementSyntax>().Any())
            {
                BlockSyntax block = node.DescendantNodes().OfType<BlockSyntax>().Single();
                if (!block.Statements.Any())
                {
                    block = SyntaxFactory.Block(new StatementSyntax[] { SyntaxFactory.ThrowStatement() });

                    node = node.WithBlock(block);
                    return node;
                }
            }
            return base.VisitCatchClause(node);
        }
Beispiel #3
0
        private async Task <Document> FixWrongCode(Document document, CatchClauseSyntax @catch, CancellationToken cancellationToken)
        {
            //procurando o bloco do catch
            var blocoCatch = @catch.DescendantNodes().OfType <BlockSyntax>().First();

            var declaracaoCatch = @catch.DescendantNodes().OfType <CatchDeclarationSyntax>().FirstOrDefault();

            CatchDeclarationSyntax novaDeclaracaoCatch = null;

            string nomeVariavelCatch = null;

            var declaracaoVariavel = declaracaoCatch.ChildTokens().FirstOrDefault(x => x.Kind() == SyntaxKind.IdentifierToken);

            //se não encontrou a variável no catch cria uma chamada ex
            //se encontrou recupera o nome da mesma para inserção posteriormente no log
            if (declaracaoVariavel == null || string.IsNullOrEmpty(declaracaoVariavel.Text))
            {
                novaDeclaracaoCatch = declaracaoCatch.WithIdentifier(SyntaxFactory.ParseToken(" ex"));
            }
            else
            {
                nomeVariavelCatch = declaracaoVariavel.Text;
            }

            //obtendo o nome do método que o catch está dentro para colocar no log
            var metodoCatchDentro = @catch.Ancestors().OfType <MethodDeclarationSyntax>().First();

            //mesma coisa para o nome da classe
            var classeCatchDentro = @catch.Ancestors().OfType <ClassDeclarationSyntax>().First();

            //criando a seguinte expressão : logger.Error(ex, "Erro no método x da classe y")
            var chamadaLog = SyntaxFactory.ExpressionStatement(
                SyntaxFactory.InvocationExpression(
                    SyntaxFactory.MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        SyntaxFactory.IdentifierName("logger"),
                        SyntaxFactory.IdentifierName("Error")))
                .WithArgumentList(
                    SyntaxFactory.ArgumentList(
                        SyntaxFactory.SeparatedList <ArgumentSyntax>(
                            new SyntaxNodeOrToken[] {
                SyntaxFactory.Argument(
                    SyntaxFactory.IdentifierName(nomeVariavelCatch ?? "ex")),
                SyntaxFactory.Token(
                    SyntaxFactory.TriviaList(),
                    SyntaxKind.CommaToken,
                    SyntaxFactory.TriviaList(
                        SyntaxFactory.Space)),
                SyntaxFactory.Argument(
                    SyntaxFactory.LiteralExpression(
                        SyntaxKind.StringLiteralExpression,
                        SyntaxFactory.Literal($"Erro no método {metodoCatchDentro.Identifier.Text} da classe {classeCatchDentro.Identifier.Text}")))
            }))))
                             .WithSemicolonToken(
                SyntaxFactory.Token(
                    SyntaxFactory.TriviaList(),
                    SyntaxKind.SemicolonToken,
                    SyntaxFactory.TriviaList(
                        SyntaxFactory.LineFeed)));

            var primeiroNoCatch = blocoCatch.ChildNodes().FirstOrDefault();

            BlockSyntax novoBlocoCatch;

            //inserindo o novo código antes do primeiro nó do catch
            if (primeiroNoCatch != null)
            {
                novoBlocoCatch = blocoCatch.InsertNodesBefore(primeiroNoCatch, new SyntaxList <StatementSyntax>(new StatementSyntax[] { chamadaLog }));
            }
            else
            {
                novoBlocoCatch = blocoCatch.WithStatements(new SyntaxList <StatementSyntax>(new StatementSyntax[] { chamadaLog }));
            }


            //formatando (como se fosse CTRL + K + D)
            var novoBlocoCatchFormatado = novoBlocoCatch.WithAdditionalAnnotations(Formatter.Annotation);

            var oldRoot = await document.GetSyntaxRootAsync(cancellationToken);

            //estou utilizando duas maneiras para o code fix pois pode haver o caso da variavel existir e ela ser reaproveitada
            //ou tem o caso que é criada uma nova variavel para o catch
            if (novaDeclaracaoCatch != null)
            {
                var newRoot = oldRoot.ReplaceNodes(new SyntaxNode[] { declaracaoCatch, blocoCatch },
                                                   (noAtual, novoNo) => { return((noAtual == declaracaoCatch) ? (SyntaxNode)novaDeclaracaoCatch : (SyntaxNode)novoBlocoCatch); });
                return(document.WithSyntaxRoot(newRoot));
            }
            else
            {
                var newRoot = oldRoot.ReplaceNode(blocoCatch, novoBlocoCatchFormatado);
                return(document.WithSyntaxRoot(newRoot));
            }
        }