Example #1
0
        private static bool UsedOutsideParentBlock(SemanticModel semanticModel, StatementSyntax expressionStatement, ISymbol identitySymbol)
        {
            var block       = expressionStatement.FirstAncestorOrSelf <BlockSyntax>();
            var method      = expressionStatement.FirstAncestorOrSelf <MethodDeclarationSyntax>();
            var methodBlock = method.Body;

            if (methodBlock.Equals(block))
            {
                return(false);
            }
            var collectionOfStatementsAfter = GetStatementsInBlocksAfter(block);

            foreach (var allStatementsAfterBlock in collectionOfStatementsAfter)
            {
                if (!allStatementsAfterBlock.Any())
                {
                    continue;
                }
                var dataFlowAnalysis = semanticModel.AnalyzeDataFlow(allStatementsAfterBlock.First(), allStatementsAfterBlock.Last());
                if (!dataFlowAnalysis.Succeeded)
                {
                    continue;
                }
                var isUsed = dataFlowAnalysis.ReadInside.Contains(identitySymbol) ||
                             dataFlowAnalysis.WrittenInside.Contains(identitySymbol);
                if (isUsed)
                {
                    return(true);
                }
            }
            return(false);
        }
Example #2
0
        private static List <List <StatementSyntax> > GetStatementsInBlocksAfter(StatementSyntax node)
        {
            var collectionOfStatements = new List <List <StatementSyntax> >();
            var method = node.FirstAncestorOrSelf <MethodDeclarationSyntax>();

            if (method?.Body == null)
            {
                return(collectionOfStatements);
            }
            var currentBlock = node.FirstAncestorOfType <BlockSyntax>();

            while (currentBlock != null)
            {
                var statements = new List <StatementSyntax>();
                foreach (var statement in currentBlock.Statements)
                {
                    if (statement.SpanStart > node.SpanStart)
                    {
                        statements.Add(statement);
                    }
                }
                if (statements.Any())
                {
                    collectionOfStatements.Add(statements);
                }
                if (method.Body.Equals(currentBlock))
                {
                    break;
                }
                currentBlock = currentBlock.FirstAncestorOfType <BlockSyntax>();
            }
            return(collectionOfStatements);
        }
Example #3
0
        private static IList <StatementSyntax> GetChildStatementsAfter(StatementSyntax node)
        {
            var block      = node.FirstAncestorOrSelf <BlockSyntax>();
            var statements = block.Statements.Where(s => s.SpanStart > node.SpanStart).ToList();

            return(statements);
        }
 private static Document MakeObjectInitializer(Document document, SyntaxNode root, StatementSyntax statement, ISymbol variableSymbol, SemanticModel semanticModel)
 {
     var blockParent = statement.FirstAncestorOrSelf<BlockSyntax>();
     var objectCreationExpression = statement.DescendantNodes().OfType<ObjectCreationExpressionSyntax>().Single();
     var newBlockParent = CreateNewBlockParent(statement, semanticModel, objectCreationExpression, variableSymbol);
     var newRoot = root.ReplaceNode(blockParent, newBlockParent);
     var newDocument = document.WithSyntaxRoot(newRoot);
     return newDocument;
 }
        private static Document MakeObjectInitializer(Document document, SyntaxNode root, StatementSyntax statement, ISymbol variableSymbol, SemanticModel semanticModel)
        {
            var blockParent = statement.FirstAncestorOrSelf <BlockSyntax>();
            var objectCreationExpression = statement.DescendantNodes().OfType <ObjectCreationExpressionSyntax>().First();
            var newBlockParent           = CreateNewBlockParent(statement, semanticModel, objectCreationExpression, variableSymbol);
            var newRoot     = root.ReplaceNode(blockParent, newBlockParent);
            var newDocument = document.WithSyntaxRoot(newRoot);

            return(newDocument);
        }
 private static BlockSyntax CreateNewBlockParent(StatementSyntax statement, SemanticModel semanticModel, ObjectCreationExpressionSyntax objectCreationExpression, ISymbol variableSymbol)
 {
     var blockParent = statement.FirstAncestorOrSelf<BlockSyntax>();
     var assignmentExpressions = ObjectInitializerAnalyzer.FindAssignmentExpressions(semanticModel, statement, variableSymbol);
     var newBlockParent = SyntaxFactory.Block()
         .WithLeadingTrivia(blockParent.GetLeadingTrivia())
         .WithTrailingTrivia(blockParent.GetTrailingTrivia())
         .WithAdditionalAnnotations(Formatter.Annotation);
     var newAssignmentExpressions = new List<ExpressionStatementSyntax>();
     for (int i = 0; i < blockParent.Statements.Count; i++)
     {
         var blockStatement = blockParent.Statements[i];
         if (blockStatement.Equals(statement))
         {
             var initializationExpressions = new List<AssignmentExpressionSyntax>();
             foreach (var expressionStatement in assignmentExpressions)
             {
                 var assignmentExpression = expressionStatement.Expression as AssignmentExpressionSyntax;
                 var memberAccess = assignmentExpression.Left as MemberAccessExpressionSyntax;
                 var propertyIdentifier = memberAccess.Name as IdentifierNameSyntax;
                 initializationExpressions.Add(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, propertyIdentifier, assignmentExpression.Right));
             }
             var initializers = SyntaxFactory.SeparatedList<ExpressionSyntax>(initializationExpressions);
             var newObjectCreationExpression = objectCreationExpression.WithInitializer(
                 SyntaxFactory.InitializerExpression(
                     SyntaxKind.ObjectInitializerExpression,
                     SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.OpenBraceToken, SyntaxFactory.ParseTrailingTrivia("\n")),
                     initializers,
                     SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.CloseBraceToken, SyntaxFactory.ParseTrailingTrivia(""))
                 ))
                 .WithLeadingTrivia(objectCreationExpression.GetLeadingTrivia())
                 .WithTrailingTrivia(objectCreationExpression.GetTrailingTrivia())
                 .WithAdditionalAnnotations(Formatter.Annotation);
             if (newObjectCreationExpression.ArgumentList?.Arguments.Count == 0)
             {
                 newObjectCreationExpression = newObjectCreationExpression.WithArgumentList(null);
             }
             var newLocalDeclarationStatement = statement.ReplaceNode(objectCreationExpression, newObjectCreationExpression)
                 .WithLeadingTrivia(statement.GetLeadingTrivia())
                 .WithTrailingTrivia(statement.GetTrailingTrivia())
                 .WithAdditionalAnnotations(Formatter.Annotation);
             newBlockParent = newBlockParent.AddStatements(newLocalDeclarationStatement);
             i += initializationExpressions.Count;
         }
         else
         {
             newBlockParent = newBlockParent.AddStatements(blockStatement
                 .WithLeadingTrivia(blockStatement.GetLeadingTrivia())
                 .WithTrailingTrivia(blockStatement.GetTrailingTrivia())
                 .WithAdditionalAnnotations(Formatter.Annotation));
         }
     }
     return newBlockParent;
 }
Example #7
0
        private async Task <Document> MakeObjectInitializerAsync(Document document, StatementSyntax statement, ISymbol variableSymbol, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var blockParent = statement.FirstAncestorOrSelf <BlockSyntax>();
            var objectCreationExpression = statement.DescendantNodes().OfType <ObjectCreationExpressionSyntax>().Single();
            var newBlockParent           = CreateNewBlockParent(statement, semanticModel, objectCreationExpression, variableSymbol);
            var root = await document.GetSyntaxRootAsync(cancellationToken);

            var newRoot     = root.ReplaceNode(blockParent, newBlockParent);
            var newDocument = document.WithSyntaxRoot(newRoot);

            return(newDocument);
        }
        public static List <ExpressionStatementSyntax> FindAssingmentExpressions(SemanticModel semanticModel, StatementSyntax statement, ISymbol variableSymbol)
        {
            var blockParent           = statement.FirstAncestorOrSelf <BlockSyntax>();
            var isBefore              = true;
            var assignmentExpressions = new List <ExpressionStatementSyntax>();

            foreach (var blockStatement in blockParent.Statements)
            {
                if (isBefore)
                {
                    if (blockStatement.Equals(statement))
                    {
                        isBefore = false;
                    }
                }
                else
                {
                    var expressionStatement = blockStatement as ExpressionStatementSyntax;
                    if (expressionStatement == null)
                    {
                        break;
                    }
                    var assignmentExpression = expressionStatement.Expression as AssignmentExpressionSyntax;
                    if (assignmentExpression == null || !assignmentExpression.IsKind(SyntaxKind.SimpleAssignmentExpression))
                    {
                        break;
                    }
                    var memberAccess = assignmentExpression.Left as MemberAccessExpressionSyntax;
                    if (memberAccess == null || !memberAccess.IsKind(SyntaxKind.SimpleMemberAccessExpression))
                    {
                        break;
                    }
                    var memberIdentifier = memberAccess.Expression as IdentifierNameSyntax;
                    if (memberIdentifier == null)
                    {
                        break;
                    }
                    var propertyIdentifier = memberAccess.Name as IdentifierNameSyntax;
                    if (propertyIdentifier == null)
                    {
                        break;
                    }
                    if (!semanticModel.GetSymbolInfo(memberIdentifier).Symbol.Equals(variableSymbol))
                    {
                        break;
                    }
                    assignmentExpressions.Add(expressionStatement);
                }
            }

            return(assignmentExpressions);
        }
Example #9
0
        private static BlockSyntax CreateNewBlockParent(StatementSyntax statement, SemanticModel semanticModel, ObjectCreationExpressionSyntax objectCreationExpression, ISymbol variableSymbol)
        {
            var blockParent           = statement.FirstAncestorOrSelf <BlockSyntax>();
            var assignmentExpressions = ObjectInitializerAnalyzer.FindAssingmentExpressions(semanticModel, statement, variableSymbol);
            var newBlockParent        = SyntaxFactory.Block()
                                        .WithLeadingTrivia(blockParent.GetLeadingTrivia())
                                        .WithTrailingTrivia(blockParent.GetTrailingTrivia())
                                        .WithAdditionalAnnotations(Formatter.Annotation);
            var newAssignmentExpressions = new List <ExpressionStatementSyntax>();

            for (int i = 0; i < blockParent.Statements.Count; i++)
            {
                var blockStatement = blockParent.Statements[i];
                if (blockStatement.Equals(statement))
                {
                    var initializationExpressions = new List <AssignmentExpressionSyntax>();
                    foreach (var expressionStatement in assignmentExpressions)
                    {
                        var assignmentExpression = expressionStatement.Expression as AssignmentExpressionSyntax;
                        var memberAccess         = assignmentExpression.Left as MemberAccessExpressionSyntax;
                        var propertyIdentifier   = memberAccess.Name as IdentifierNameSyntax;
                        initializationExpressions.Add(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, propertyIdentifier, assignmentExpression.Right));
                    }
                    var initializers = SyntaxFactory.SeparatedList <ExpressionSyntax>(initializationExpressions);
                    var newObjectCreationExpression = objectCreationExpression.WithInitializer(
                        SyntaxFactory.InitializerExpression(
                            SyntaxKind.ObjectInitializerExpression,
                            SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.OpenBraceToken, SyntaxFactory.ParseTrailingTrivia("\n")),
                            initializers,
                            SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.CloseBraceToken, SyntaxFactory.ParseTrailingTrivia(""))
                            ))
                                                      .WithLeadingTrivia(objectCreationExpression.GetLeadingTrivia())
                                                      .WithTrailingTrivia(objectCreationExpression.GetTrailingTrivia())
                                                      .WithAdditionalAnnotations(Formatter.Annotation);
                    var newLocalDeclarationStatement = statement.ReplaceNode(objectCreationExpression, newObjectCreationExpression)
                                                       .WithLeadingTrivia(statement.GetLeadingTrivia())
                                                       .WithTrailingTrivia(statement.GetTrailingTrivia())
                                                       .WithAdditionalAnnotations(Formatter.Annotation);
                    newBlockParent = newBlockParent.AddStatements(newLocalDeclarationStatement);
                    i += initializationExpressions.Count;
                }
                else
                {
                    newBlockParent = newBlockParent.AddStatements(blockStatement
                                                                  .WithLeadingTrivia(blockStatement.GetLeadingTrivia())
                                                                  .WithTrailingTrivia(blockStatement.GetTrailingTrivia())
                                                                  .WithAdditionalAnnotations(Formatter.Annotation));
                }
            }

            return(newBlockParent);
        }
Example #10
0
        private static bool IsDisposedOrAssigned(SemanticModel semanticModel, StatementSyntax statement, ILocalSymbol identitySymbol)
        {
            var method = statement.FirstAncestorOrSelf <MethodDeclarationSyntax>();

            if (method == null)
            {
                return(false);
            }
            if (IsReturned(method, statement, semanticModel, identitySymbol))
            {
                return(true);
            }
            foreach (var childStatements in method.Body.DescendantNodes().OfType <StatementSyntax>())
            {
                if (childStatements.SpanStart > statement.SpanStart &&
                    (IsCorrectDispose(childStatements as ExpressionStatementSyntax, semanticModel, identitySymbol) ||
                     IsAssignedToField(childStatements as ExpressionStatementSyntax, semanticModel, identitySymbol)))
                {
                    return(true);
                }
            }
            return(false);
        }
 private static IList<StatementSyntax> GetChildStatementsAfter(StatementSyntax node)
 {
     var block = node.FirstAncestorOrSelf<BlockSyntax>();
     var statements = block.Statements.Where(s => s.SpanStart > node.SpanStart).ToList();
     return statements;
 }
 private static List<List<StatementSyntax>> GetStatementsInBlocksAfter(StatementSyntax node)
 {
     var collectionOfStatements = new List<List<StatementSyntax>>();
     var method = node.FirstAncestorOrSelf<MethodDeclarationSyntax>();
     if (method?.Body == null) return collectionOfStatements;
     var currentBlock = node.FirstAncestorOfType<BlockSyntax>();
     while (currentBlock != null)
     {
         var statements = new List<StatementSyntax>();
         foreach (var statement in currentBlock.Statements)
             if (statement.SpanStart > node.SpanStart)
                 statements.Add(statement);
         if (statements.Any()) collectionOfStatements.Add(statements);
         if (method.Body.Equals(currentBlock)) break;
         currentBlock = currentBlock.FirstAncestorOfType<BlockSyntax>();
     }
     return collectionOfStatements;
 }
 private static bool UsedOutsideParentBlock(SemanticModel semanticModel, StatementSyntax expressionStatement, ISymbol identitySymbol)
 {
     var block = expressionStatement.FirstAncestorOrSelf<BlockSyntax>();
     var method = expressionStatement.FirstAncestorOrSelf<MethodDeclarationSyntax>();
     var methodBlock = method.Body;
     if (methodBlock.Equals(block)) return false;
     var collectionOfStatementsAfter = GetStatementsInBlocksAfter(block);
     foreach (var allStatementsAfterBlock in collectionOfStatementsAfter)
     {
         if (!allStatementsAfterBlock.Any()) continue;
         var dataFlowAnalysis = semanticModel.AnalyzeDataFlow(allStatementsAfterBlock.First(), allStatementsAfterBlock.Last());
         if (!dataFlowAnalysis.Succeeded) continue;
         var isUsed = dataFlowAnalysis.ReadInside.Contains(identitySymbol)
             || dataFlowAnalysis.WrittenInside.Contains(identitySymbol);
         if (isUsed) return true;
     }
     return false;
 }
Example #14
0
        private static void AnalyzeObjectCreation(SyntaxNodeAnalysisContext context)
        {
            if (context.IsGenerated())
            {
                return;
            }
            var objectCreation = context.Node as ObjectCreationExpressionSyntax;

            if (objectCreation == null)
            {
                return;
            }
            if (objectCreation?.Parent is UsingStatementSyntax)
            {
                return;
            }
            if (objectCreation?.Parent is ReturnStatementSyntax)
            {
                return;
            }
            if (objectCreation.Ancestors().Any(i => i.IsAnyKind(
                                                   SyntaxKind.ThisConstructorInitializer,
                                                   SyntaxKind.BaseConstructorInitializer,
                                                   SyntaxKind.ObjectCreationExpression)))
            {
                return;
            }

            var semanticModel = context.SemanticModel;
            var type          = semanticModel.GetSymbolInfo(objectCreation.Type).Symbol as INamedTypeSymbol;

            if (type == null)
            {
                return;
            }
            if (!type.AllInterfaces.Any(i => i.ToString() == "System.IDisposable"))
            {
                return;
            }
            ISymbol         identitySymbol = null;
            StatementSyntax statement      = null;

            if (objectCreation.Parent.IsKind(SyntaxKind.SimpleAssignmentExpression))
            {
                var assignmentExpression = (AssignmentExpressionSyntax)objectCreation.Parent;
                identitySymbol = semanticModel.GetSymbolInfo(assignmentExpression.Left).Symbol;
                if (identitySymbol?.Kind != SymbolKind.Local)
                {
                    return;
                }
                if (assignmentExpression.FirstAncestorOrSelf <MethodDeclarationSyntax>() == null)
                {
                    return;
                }
                var usingStatement = assignmentExpression.Parent as UsingStatementSyntax;
                if (usingStatement != null)
                {
                    return;
                }
                statement = assignmentExpression.Parent as ExpressionStatementSyntax;
            }
            else if (objectCreation.Parent.IsKind(SyntaxKind.EqualsValueClause) && objectCreation.Parent.Parent.IsKind(SyntaxKind.VariableDeclarator))
            {
                var variableDeclarator  = (VariableDeclaratorSyntax)objectCreation.Parent.Parent;
                var variableDeclaration = variableDeclarator?.Parent as VariableDeclarationSyntax;
                identitySymbol = semanticModel.GetDeclaredSymbol(variableDeclarator);
                if (identitySymbol == null)
                {
                    return;
                }
                var usingStatement = variableDeclaration?.Parent as UsingStatementSyntax;
                if (usingStatement != null)
                {
                    return;
                }
                statement = variableDeclaration.Parent as LocalDeclarationStatementSyntax;
                if ((statement?.FirstAncestorOrSelf <MethodDeclarationSyntax>()) == null)
                {
                    return;
                }
            }
            else
            {
                var props = new Dictionary <string, string> {
                    { "typeName", type.Name }
                }.ToImmutableDictionary();
                context.ReportDiagnostic(Diagnostic.Create(Rule, objectCreation.GetLocation(), props, type.Name.ToString()));
                return;
            }
            if (statement != null && identitySymbol != null)
            {
                var isDisposeOrAssigned = IsDisposedOrAssigned(semanticModel, statement, (ILocalSymbol)identitySymbol);
                if (isDisposeOrAssigned)
                {
                    return;
                }
                var props = new Dictionary <string, string> {
                    { "typeName", type.Name }
                }.ToImmutableDictionary();
                context.ReportDiagnostic(Diagnostic.Create(Rule, objectCreation.GetLocation(), props, type.Name.ToString()));
            }
        }
        private static BlockSyntax CreateNewBlockParent(StatementSyntax statement, SemanticModel semanticModel, ObjectCreationExpressionSyntax objectCreationExpression, ISymbol variableSymbol)
        {
            var blockParent = statement.FirstAncestorOrSelf<BlockSyntax>();
            var assignmentExpressions = ObjectInitializerAnalyzer.FindAssignmentExpressions(semanticModel, statement, variableSymbol);
            var newBlockParent = SyntaxFactory.Block()
                .WithLeadingTrivia(blockParent.GetLeadingTrivia())
                .WithTrailingTrivia(blockParent.GetTrailingTrivia())
                .WithAdditionalAnnotations(Formatter.Annotation);

            for (int i = 0; i < blockParent.Statements.Count; i++)
            {
                var blockStatement = blockParent.Statements[i];
                if (blockStatement.Equals(statement))
                {
                    var initializationExpressions = new List<AssignmentExpressionSyntax>();
                    foreach (var expressionStatement in assignmentExpressions)
                    {
                        var assignmentExpression = expressionStatement.Expression as AssignmentExpressionSyntax;
                        var memberAccess = assignmentExpression.Left as MemberAccessExpressionSyntax;
                        var propertyIdentifier = memberAccess.Name as IdentifierNameSyntax;
                        var newAssignmentExpression = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, propertyIdentifier, assignmentExpression.Right);
                        initializationExpressions.Add(newAssignmentExpression.WithTriviaFrom(expressionStatement));
                    }

                    if (objectCreationExpression.Initializer != null)
                    {
                        var existentInitilizers = objectCreationExpression.Initializer.Expressions.Cast<AssignmentExpressionSyntax>()
                            .Where(ae =>
                            {
                                var propertyIdentifier = ae.Left.ToFullString().Trim();
                                return initializationExpressions.All(ie => ie.Left.ToFullString().Trim() != propertyIdentifier);
                            })
                            .Select(ae => ae.WithoutTrivia())
                            .ToList();
                        initializationExpressions.InsertRange(0, existentInitilizers);
                    }

                    // Trailing trivia will be added before the separator if a simple separator list is used.  This builds the separator token for expression
                    // such that the trailing trivia from the original expression is added after the comma on the same line.
                    var initializerSeparators = initializationExpressions.Take(initializationExpressions.Count - 1).Select(expr => SyntaxFactory.Token(SyntaxKind.CommaToken).WithTrailingTrivia(expr.GetTrailingTrivia())).ToList();
                    var lastInitializer = initializationExpressions.Last(); // Preserve the last initializer before rebuilding the list.
                    // Get all but the last initializer without the trailing trivia.  Trivia will be added after the separator from the list above.
                    initializationExpressions = initializationExpressions.Take(initializationExpressions.Count - 1).Select(expr => expr.WithoutTrailingTrivia()).ToList();
                    initializationExpressions.Add(lastInitializer); // Add the last initializer with all of its trivia.

                    var initializers = SyntaxFactory.SeparatedList<ExpressionSyntax>(initializationExpressions, initializerSeparators);

                    var newObjectCreationExpression = objectCreationExpression.WithInitializer(
                        SyntaxFactory.InitializerExpression(
                            SyntaxKind.ObjectInitializerExpression,
                            SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.OpenBraceToken, SyntaxFactory.ParseTrailingTrivia(Environment.NewLine)),
                            initializers,
                            SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.CloseBraceToken, SyntaxFactory.ParseTrailingTrivia(""))
                        ))
                        .WithLeadingTrivia(objectCreationExpression.GetLeadingTrivia())
                        .WithTrailingTrivia(objectCreationExpression.GetTrailingTrivia())
                        .WithAdditionalAnnotations(Formatter.Annotation);
                    if (newObjectCreationExpression.ArgumentList?.Arguments.Count == 0)
                    {
                        newObjectCreationExpression = newObjectCreationExpression.WithArgumentList(null);
                    }
                    var newLocalDeclarationStatement = statement.ReplaceNode(objectCreationExpression, newObjectCreationExpression)
                        .WithLeadingTrivia(statement.GetLeadingTrivia())
                        .WithTrailingTrivia(statement.GetTrailingTrivia())
                        .WithAdditionalAnnotations(Formatter.Annotation);
                    newBlockParent = newBlockParent.AddStatements(newLocalDeclarationStatement);
                    i += initializationExpressions.Count;
                }
                else
                {
                    newBlockParent = newBlockParent.AddStatements(blockStatement
                        .WithLeadingTrivia(blockStatement.GetLeadingTrivia())
                        .WithTrailingTrivia(blockStatement.GetTrailingTrivia())
                        .WithAdditionalAnnotations(Formatter.Annotation));
                }
            }
            return newBlockParent;
        }
 public static List<ExpressionStatementSyntax> FindAssignmentExpressions(SemanticModel semanticModel, StatementSyntax statement, ISymbol variableSymbol)
 {
     var blockParent = statement.FirstAncestorOrSelf<BlockSyntax>();
     var isBefore = true;
     var assignmentExpressions = new List<ExpressionStatementSyntax>();
     foreach (var blockStatement in blockParent.Statements)
     {
         if (isBefore)
         {
             if (blockStatement.Equals(statement)) isBefore = false;
         }
         else
         {
             var expressionStatement = blockStatement as ExpressionStatementSyntax;
             if (expressionStatement == null) break;
             var assignmentExpression = expressionStatement.Expression as AssignmentExpressionSyntax;
             if (assignmentExpression == null || !assignmentExpression.IsKind(SyntaxKind.SimpleAssignmentExpression)) break;
             var memberAccess = assignmentExpression.Left as MemberAccessExpressionSyntax;
             if (memberAccess == null || !memberAccess.IsKind(SyntaxKind.SimpleMemberAccessExpression)) break;
             var memberIdentifier = memberAccess.Expression as IdentifierNameSyntax;
             if (memberIdentifier == null) break;
             var propertyIdentifier = memberAccess.Name as IdentifierNameSyntax;
             if (propertyIdentifier == null) break;
             if (!semanticModel.GetSymbolInfo(memberIdentifier).Symbol.Equals(variableSymbol)) break;
             assignmentExpressions.Add(expressionStatement);
         }
     }
     return assignmentExpressions;
 }
 private static bool IsDisposedOrAssigned(SemanticModel semanticModel, StatementSyntax statement, ILocalSymbol identitySymbol)
 {
     var method = statement.FirstAncestorOrSelf<MethodDeclarationSyntax>();
     if (method == null) return false;
     if (IsReturned(method, statement, semanticModel, identitySymbol)) return true;
     foreach (var childStatements in method.Body.DescendantNodes().OfType<StatementSyntax>())
     {
         if (childStatements.SpanStart > statement.SpanStart
         && (IsCorrectDispose(childStatements as ExpressionStatementSyntax, semanticModel, identitySymbol)
         || IsAssignedToField(childStatements as ExpressionStatementSyntax, semanticModel, identitySymbol)))
             return true;
     }
     return false;
 }
        private static BlockSyntax CreateNewBlockParent(StatementSyntax statement, SemanticModel semanticModel, ObjectCreationExpressionSyntax objectCreationExpression, ISymbol variableSymbol)
        {
            var blockParent           = statement.FirstAncestorOrSelf <BlockSyntax>();
            var assignmentExpressions = ObjectInitializerAnalyzer.FindAssignmentExpressions(semanticModel, statement, variableSymbol);
            var newBlockParent        = SyntaxFactory.Block()
                                        .WithLeadingTrivia(blockParent.GetLeadingTrivia())
                                        .WithTrailingTrivia(blockParent.GetTrailingTrivia())
                                        .WithAdditionalAnnotations(Formatter.Annotation);

            for (int i = 0; i < blockParent.Statements.Count; i++)
            {
                var blockStatement = blockParent.Statements[i];
                if (blockStatement.Equals(statement))
                {
                    var initializationExpressions = new List <AssignmentExpressionSyntax>();
                    foreach (var expressionStatement in assignmentExpressions)
                    {
                        var assignmentExpression    = expressionStatement.Expression as AssignmentExpressionSyntax;
                        var memberAccess            = assignmentExpression.Left as MemberAccessExpressionSyntax;
                        var propertyIdentifier      = memberAccess.Name as IdentifierNameSyntax;
                        var newAssignmentExpression = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, propertyIdentifier, assignmentExpression.Right);
                        initializationExpressions.Add(newAssignmentExpression.WithTriviaFrom(expressionStatement));
                    }

                    if (objectCreationExpression.Initializer != null)
                    {
                        var existentInitilizers = objectCreationExpression.Initializer.Expressions.Cast <AssignmentExpressionSyntax>()
                                                  .Where(ae =>
                        {
                            var propertyIdentifier = ae.Left.ToFullString().Trim();
                            return(initializationExpressions.All(ie => ie.Left.ToFullString().Trim() != propertyIdentifier));
                        })
                                                  .Select(ae => ae.WithoutTrivia())
                                                  .ToList();
                        initializationExpressions.InsertRange(0, existentInitilizers);
                    }

                    // Trailing trivia will be added before the separator if a simple separator list is used.  This builds the separator token for expression
                    // such that the trailing trivia from the original expression is added after the comma on the same line.
                    var initializerSeparators = initializationExpressions.Take(initializationExpressions.Count - 1).Select(expr => SyntaxFactory.Token(SyntaxKind.CommaToken).WithTrailingTrivia(expr.GetTrailingTrivia())).ToList();
                    var lastInitializer       = initializationExpressions.Last(); // Preserve the last initializer before rebuilding the list.
                    // Get all but the last initializer without the trailing trivia.  Trivia will be added after the separator from the list above.
                    initializationExpressions = initializationExpressions.Take(initializationExpressions.Count - 1).Select(expr => expr.WithoutTrailingTrivia()).ToList();
                    initializationExpressions.Add(lastInitializer); // Add the last initializer with all of its trivia.

                    var initializers = SyntaxFactory.SeparatedList <ExpressionSyntax>(initializationExpressions, initializerSeparators);

                    var newObjectCreationExpression = objectCreationExpression.WithInitializer(
                        SyntaxFactory.InitializerExpression(
                            SyntaxKind.ObjectInitializerExpression,
                            SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.OpenBraceToken, SyntaxFactory.ParseTrailingTrivia(Environment.NewLine)),
                            initializers,
                            SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.CloseBraceToken, SyntaxFactory.ParseTrailingTrivia(""))
                            ))
                                                      .WithLeadingTrivia(objectCreationExpression.GetLeadingTrivia())
                                                      .WithTrailingTrivia(objectCreationExpression.GetTrailingTrivia())
                                                      .WithAdditionalAnnotations(Formatter.Annotation);
                    if (newObjectCreationExpression.ArgumentList?.Arguments.Count == 0)
                    {
                        newObjectCreationExpression = newObjectCreationExpression.WithArgumentList(null);
                    }
                    var newLocalDeclarationStatement = statement.ReplaceNode(objectCreationExpression, newObjectCreationExpression)
                                                       .WithLeadingTrivia(statement.GetLeadingTrivia())
                                                       .WithTrailingTrivia(statement.GetTrailingTrivia())
                                                       .WithAdditionalAnnotations(Formatter.Annotation);
                    newBlockParent = newBlockParent.AddStatements(newLocalDeclarationStatement);
                    i += assignmentExpressions.Count;
                }
                else
                {
                    newBlockParent = newBlockParent.AddStatements(blockStatement
                                                                  .WithLeadingTrivia(blockStatement.GetLeadingTrivia())
                                                                  .WithTrailingTrivia(blockStatement.GetTrailingTrivia())
                                                                  .WithAdditionalAnnotations(Formatter.Annotation));
                }
            }
            return(newBlockParent);
        }
Example #19
0
        private static BlockSyntax CreateNewBlockParent(StatementSyntax statement, SemanticModel semanticModel, ObjectCreationExpressionSyntax objectCreationExpression, ISymbol variableSymbol)
        {
            var blockParent           = statement.FirstAncestorOrSelf <BlockSyntax>();
            var assignmentExpressions = ObjectInitializerAnalyzer.FindAssignmentExpressions(semanticModel, statement, variableSymbol);
            var newBlockParent        = SyntaxFactory.Block()
                                        .WithLeadingTrivia(blockParent.GetLeadingTrivia())
                                        .WithTrailingTrivia(blockParent.GetTrailingTrivia())
                                        .WithAdditionalAnnotations(Formatter.Annotation);

            for (int i = 0; i < blockParent.Statements.Count; i++)
            {
                var blockStatement = blockParent.Statements[i];
                if (blockStatement.Equals(statement))
                {
                    var initializationExpressions = new List <AssignmentExpressionSyntax>();

                    foreach (var expressionStatement in assignmentExpressions)
                    {
                        var assignmentExpression    = expressionStatement.Expression as AssignmentExpressionSyntax;
                        var memberAccess            = assignmentExpression.Left as MemberAccessExpressionSyntax;
                        var propertyIdentifier      = memberAccess.Name as IdentifierNameSyntax;
                        var newAssignmentExpression = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, propertyIdentifier, assignmentExpression.Right);
                        initializationExpressions.Add(newAssignmentExpression);
                    }

                    if (objectCreationExpression.Initializer != null)
                    {
                        var existentInitilizers = objectCreationExpression.Initializer.Expressions.Cast <AssignmentExpressionSyntax>()
                                                  .Where(ae =>
                        {
                            var propertyIdentifier = ae.Left.ToFullString().Trim();
                            return(initializationExpressions.All(ie => ie.Left.ToFullString().Trim() != propertyIdentifier));
                        })
                                                  .Select(ae => ae.WithoutTrivia())
                                                  .ToList();
                        initializationExpressions.InsertRange(0, existentInitilizers);
                    }

                    var initializers = SyntaxFactory.SeparatedList <ExpressionSyntax>(initializationExpressions);

                    var newObjectCreationExpression = objectCreationExpression.WithInitializer(
                        SyntaxFactory.InitializerExpression(
                            SyntaxKind.ObjectInitializerExpression,
                            SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.OpenBraceToken, SyntaxFactory.ParseTrailingTrivia(Environment.NewLine)),
                            initializers,
                            SyntaxFactory.Token(SyntaxFactory.ParseLeadingTrivia(" "), SyntaxKind.CloseBraceToken, SyntaxFactory.ParseTrailingTrivia(""))
                            ))
                                                      .WithLeadingTrivia(objectCreationExpression.GetLeadingTrivia())
                                                      .WithTrailingTrivia(objectCreationExpression.GetTrailingTrivia())
                                                      .WithAdditionalAnnotations(Formatter.Annotation);
                    if (newObjectCreationExpression.ArgumentList?.Arguments.Count == 0)
                    {
                        newObjectCreationExpression = newObjectCreationExpression.WithArgumentList(null);
                    }
                    var newLocalDeclarationStatement = statement.ReplaceNode(objectCreationExpression, newObjectCreationExpression)
                                                       .WithLeadingTrivia(statement.GetLeadingTrivia())
                                                       .WithTrailingTrivia(statement.GetTrailingTrivia())
                                                       .WithAdditionalAnnotations(Formatter.Annotation);
                    newBlockParent = newBlockParent.AddStatements(newLocalDeclarationStatement);
                    i += initializationExpressions.Count;
                }
                else
                {
                    newBlockParent = newBlockParent.AddStatements(blockStatement
                                                                  .WithLeadingTrivia(blockStatement.GetLeadingTrivia())
                                                                  .WithTrailingTrivia(blockStatement.GetTrailingTrivia())
                                                                  .WithAdditionalAnnotations(Formatter.Annotation));
                }
            }
            return(newBlockParent);
        }
        public Document GetRefactoredDocument(CancellationToken cancellationToken)
        {
            lock (this) {
                var start = DateTime.Now;

                Utils.Trace(string.Format("Trying to extract method, span: {0}", this.textSpan));

                var localDocument = document;

                var extracted = ExtractMethodService.ExtractMethod(localDocument, this.textSpan, new ExtractMethodOptions(true), cancellationToken);

                Utils.TraceTime("Roslyn extract method", DateTime.Now - start);

                if (!extracted.Succeeded)
                {
                    Utils.Trace("Method Extraction failed!");
                    return(null);
                }
                Utils.Trace("Extract method: ok");

                var clock = DateTime.Now;

                var resultingTree = localDocument.GetSyntaxTree(cancellationToken).GetRoot(cancellationToken);

                var newMethodSyntax = extracted.MethodDeclarationNode as MethodDeclarationSyntax;
                if (newMethodSyntax == null)
                {
                    return(null);
                }

                var body = newMethodSyntax.Body;

                var compilationUnitDeclaration = resultingTree as CompilationUnitSyntax;
                if (compilationUnitDeclaration == null)
                {
                    return(null);
                }
                var oldTree = localDocument.GetSyntaxTree(cancellationToken);
                if (oldTree == null)
                {
                    return(null);
                }

                Utils.Trace("Got the original syntax tree");

                var oldRoot = oldTree.GetRoot() as SyntaxNode;

                // find the smallest containing statement (and the
                Utils.Trace("Searching for the statement containing the new call");
                StatementSyntax containingStatement = extracted.InvocationNameToken.Parent.FirstAncestorOrSelf <StatementSyntax>();
                if (containingStatement == null)
                {
                    Utils.Trace("No containing statement found. Aborting");
                    return(null);
                }
                Utils.Trace("Containing statement found");

                Utils.Trace("Searching for the right spots where to place the placeholder calls");

                var oldText = oldTree.GetText().ToString();
                var beforeRefactoringText = oldText.Substring(0, containingStatement.Span.Start - 1);
                var afterRefactoringText  = oldText.Substring(containingStatement.Span.Start + containingStatement.Span.Length);

                //var sub = oldText.Substring(containingStatement.Span.Start, containingStatement.Span.Length);
                var sub = oldText.Substring(this.textSpan.Start, this.textSpan.Length);

                Utils.Trace("Generating the Precondition marker");

                var actualParameters = "";
                var formalParameters = "";

                var ps = newMethodSyntax.ParameterList.Parameters;
                for (int i = 0, j = 0, n = ps.Count; i < n; i++)
                {
                    var p = ps[i];
                    {
                        var modifiers = "";

                        foreach (var modifier in p.Modifiers)
                        {
                            modifiers = modifiers + modifier.ValueText + " ";
                        }

                        // Avoid the refs when emitting the condition
                        if (!String.IsNullOrEmpty(modifiers))
                        {
                            if (0 < j)
                            {
                                actualParameters += ",";
                                formalParameters += ",";
                            }

                            var name = p.Identifier.ValueText;
                            actualParameters += name;
                            formalParameters += p.Type + " " + name;

                            j++;
                        }
                    }
                }

                // todo: just use invocation, but replace the method name with __PreconditionMarker!
                var preconditionMarker = "__PreconditionMarker(" + actualParameters + ");";

                Utils.Trace("Generating the Postcondition marker");

                var postconditionMarker = "__PostconditionMarker(" + (actualParameters.Length > 0 ? actualParameters : "");

                BinaryExpressionSyntax assignment = null;
                var invocationExpression          = extracted.InvocationNameToken.Parent.Parent as InvocationExpressionSyntax;
                if (invocationExpression != null)
                {
                    var expression = invocationExpression.Parent.FirstAncestorOrSelf <ExpressionSyntax>();
                    if (expression != null && expression.Kind == SyntaxKind.AssignExpression)
                    {
                        // TODO: what about += or local declarations? should they be included?
                        assignment = (BinaryExpressionSyntax)expression;
                    }
                }

                if (assignment == null) // then the extraction was at the statement level
                {
                    postconditionMarker += (actualParameters.Length > 0 ? "," : "") + "false";
                }
                else
                {
                    postconditionMarker += (actualParameters.Length > 0 ? "," : "") + assignment.Left.GetText() + ", true";
                }
                postconditionMarker += ");";

                Utils.Trace("Searching for the enclosing method");

                // now need to climb up to enclosing method so definitions of the markers can be inserted
                MethodDeclarationSyntax containingMethod = containingStatement.FirstAncestorOrSelf <MethodDeclarationSyntax>();
                if (containingMethod == null)
                {
                    Utils.Trace("No enclosing method found: Aborting");
                    return(null);
                }

                Utils.Trace("Enclosing method found");

                Utils.Trace("Computing string positions for dummy methods");

                var beforeMethodText = oldText.Substring(0, containingMethod.Span.Start - 1);
                var inMethodBeforeRefactoringText = oldText.Substring(containingMethod.Span.Start, this.textSpan.Start - containingMethod.Span.Start);
                var remaining = oldText.Substring(this.textSpan.End);

                Utils.Trace("Adding dummy methods");

                var preconditionMarkerDef = "[Pure]\npublic void __PreconditionMarker(" + formalParameters + "){}\n";

                // It is generic only if there is a parameter representing the return value
                var postconditionMarkerDef = assignment != null ?
                                             "[Pure]\npublic void __PostconditionMarker<T>(" + formalParameters + (formalParameters.Length > 0 ? "," : "") + "T x,bool returnValue){}\n"
          :
                                             "[Pure]\npublic void __PostconditionMarker(" + formalParameters + (formalParameters.Length > 0 ? "," : "") + " bool returnValue = false){}\n"
                ;

                var newProg = String.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}",
                                            beforeMethodText, preconditionMarkerDef, postconditionMarkerDef,
                                            inMethodBeforeRefactoringText, preconditionMarker, sub, postconditionMarker,
                                            remaining);

                var newSolution = localDocument.Project.Solution.WithDocumentText(document.Id, new StringText(newProg));
                //var newSolution = localDocument.Project.Solution.UpdateDocument(document.Id, new StringText(newProg));
                localDocument = newSolution.GetDocument(document.Id);
                var newTree = localDocument.GetSyntaxTree();

                Utils.Trace("Dumping annotated tree");

                Utils.DumpCSFile(@"AnnotatedTree.cs", newTree.GetText().ToString(), @"Program with marker explicits");

                var newRoot = (CompilationUnitSyntax)newTree.GetRoot();
                if (newRoot.ContainsDiagnostics)
                {
                    return(null);
                }

                Utils.Trace("Searching the extracted method");

                MethodDeclarationSyntax newExtractedMethod, originalMethod;
                newExtractedMethod = extracted.MethodDeclarationNode as MethodDeclarationSyntax;
                if (newExtractedMethod == null)
                {
                    Utils.Trace("Extracted method not found: aborting");
                    return(null);
                }

                Utils.Trace("Extracted method found");

                originalMethod = newExtractedMethod;


                // Getting the name of the method
                MethodDeclarationSyntax methodToAnalyze = containingStatement.FirstAncestorOrSelf <MethodDeclarationSyntax>();
                if (methodToAnalyze == null)
                {
                    Utils.Trace("Extractee method not found: aborting");

                    return(null);
                }
                Utils.Trace("Extractee method found.");

                Utils.TraceTime("Generating annotated tree", DateTime.Now - clock);
                clock = DateTime.Now; // reset the clock

                // now let Clousot see the rewritten unit

                Utils.Trace("Running Clousot to extract <Ps, Qs>");

                newExtractedMethod = ExtractAndAddPsQs(ref cancellationToken, localDocument, newRoot, newExtractedMethod);

                Utils.TraceTime("Running Clousot to extract <Ps, Qs>", DateTime.Now - clock);
                clock = DateTime.Now;

                if (newExtractedMethod == null)
                {
                    Utils.Trace("Aborting: failed to infer <Ps, Qs>");

                    return(null);
                }

                Utils.Trace("Checking we have new contracts");

#if DEBUG || TRACE
                // If we added some contract
                if (newExtractedMethod == originalMethod)
                {
                    Utils.Trace("no new contract, but we continue to get the <Pm, Qm>");
                    //return null;
                }
#endif

                Utils.Trace("Creating a new tree");

                var refactoredTree = (SyntaxNode)extracted.Document.GetSyntaxRoot().ReplaceNode(originalMethod, Formatter.Annotation.AddAnnotationTo(newExtractedMethod));
                //(SyntaxNode)resultingTree.ReplaceNode(originalMethod, Formatter.Annotation.AddAnnotationTo(newExtractedMethod));

                Utils.DumpCSFile(@"RefactoredProgram.cs", refactoredTree.ToFullString(), "Program with extracted contracts (Ps, Qs)");
                //Utils.DumpCSFile(@"RefactoredProgram.cs", refactoredTree.GetFullText(), "Program with extracted contracts (Ps, Qs)");

                var annotatedMethod = ExtractAndAddPmQm(ref cancellationToken, localDocument, refactoredTree, newExtractedMethod);

                if (annotatedMethod == null)
                {
                    Utils.Trace("Aborting: failed to annotate the method");
                    return(null);
                }

                Utils.TraceTime("Running Clousot to extract <Pm, Qm>", DateTime.Now - clock);

                if (annotatedMethod != newExtractedMethod)
                {
                    Utils.Trace("Found new contracts, updating the method");
                    Utils.TraceTime("Done!", DateTime.Now - start);

                    refactoredTree = (SyntaxNode)extracted.Document.GetSyntaxRoot().ReplaceNode(originalMethod, Formatter.Annotation.AddAnnotationTo(annotatedMethod));
                }
                Utils.TraceTime("Done!", DateTime.Now - start);

                return(localDocument.WithSyntaxRoot(refactoredTree));
                //return this.editFactory.CreateTreeTransformEdit(localDocument.Project.Solution, localDocument.GetSyntaxTree(), refactoredTree);
            }
        }