private MethodDeclarationSyntax ExtractAndAddPsQs(ref CancellationToken cancellationToken, Microsoft.CodeAnalysis.Document localDocument, CompilationUnitSyntax newRoot, MethodDeclarationSyntax newExtractedMethod)
        {
            // Let Clousot see the rewritten unit

            var connectionToClousot = new RoslynToCCICodeModel.ClousotGlue();

            foreach (var result in connectionToClousot.AnalyzeMeAUnit(localDocument, newRoot, cancellationToken, this.options,
                                                                      new string[] { "-extractmethodmode", "-arrays:arraypurity", "-suggest:requires" /*"-memberNameSelect",*/ }))
            {
                Utils.Trace("Getting Clousot Result");

                String       condition;
                ContractKind kind;
                if (result.IsExtractMethodSuggestion && result.Message.TryParseSuggestion(out kind, out condition))
                {
                    Utils.Trace("Inserting Clousot result. New Condition: " + condition);

                    // Parse the condition
                    var newContract = SyntaxFactory.ParseStatement(condition + Environment.NewLine);

                    newExtractedMethod = newExtractedMethod.InsertStatements(newContract, kind);
                }
                else
                {
                    Utils.Trace("Skipped Clousot output : " + result.Message);
                }
            }

            return(newExtractedMethod);
        }
        private MethodDeclarationSyntax ExtractAndAddPmQm(ref CancellationToken cancellationToken,
                                                          Microsoft.CodeAnalysis.Document localDocument, SyntaxNode oldRoot, MethodDeclarationSyntax newExtractedMethod)
        {
            var newText = oldRoot.ToFullString();

            Utils.DumpCSFile("BeforePmQm.cs", newText);

            var newSolution = localDocument.Project.Solution.WithDocumentText(localDocument.Id, new StringText(newText));
            //var newSolution = localDocument.Project.Solution.UpdateDocument(localDocument.Id, new StringText(newText));
            var newLocalDocument = newSolution.GetDocument(localDocument.Id);

            localDocument = null; // to be sure we do not use it

            var newTree = newLocalDocument.GetSyntaxTree();

            Utils.Trace("Running Clousot to infer <Pm, Qm> and <Pr, Qr>");

            var newRoot = (CompilationUnitSyntax)newTree.GetRoot();

            if (newRoot.ContainsDiagnostics)
            {
                Utils.Trace("Aborting: the new tree has syntax errors");

                return(null);
            }

            // Let Clousot see the rewritten unit
            var connectionToClousot = new RoslynToCCICodeModel.ClousotGlue();

            foreach (var result in connectionToClousot.AnalyzeMeAUnit(newLocalDocument, newRoot, cancellationToken, this.options,
                                                                      new string[] { "-extractmethodmoderefine", newExtractedMethod.Identifier.ValueText, "-premode", "combined", "-suggest", "methodensures", "-suggest:requires" }))
            {
                Utils.Trace("Getting Clousot Result");

                String       condition;
                ContractKind kind;
                if (result.Message.TryParseSuggestion(out kind, out condition))
                {
                    Utils.Trace("Inserting Clousot result. New Condition: " + condition);

                    // Parse the condition
                    var newContract = SyntaxFactory.ParseStatement(condition + Environment.NewLine);

                    if (!newContract.ContainsDiagnostics)
                    {
                        newExtractedMethod = newExtractedMethod.InsertStatements(newContract, kind);
                    }
                    else
                    {
                        Utils.Trace("\tskipped, as it contains syntax errors");
                    }
                }
            }

            return(newExtractedMethod);
        }
    private MethodDeclarationSyntax ExtractAndAddPmQm(ref CancellationToken cancellationToken,
      Microsoft.CodeAnalysis.Document localDocument, SyntaxNode oldRoot, MethodDeclarationSyntax newExtractedMethod) {
      var newText = oldRoot.ToFullString();

      cancellationToken.ThrowIfCancellationRequested();

      Utils.DumpCSFile("BeforePmQm.cs", newText);

      var newSolution = localDocument.Project.Solution.WithDocumentText(localDocument.Id, SourceText.From(newText));
      //var newSolution = localDocument.Project.Solution.UpdateDocument(localDocument.Id, SourceText.From(newText));
      var newLocalDocument = newSolution.GetDocument(localDocument.Id);

      localDocument = null; // to be sure we do not use it

      var newTree = newLocalDocument.GetSyntaxTree();

      Utils.Trace("Running Clousot to infer <Pm, Qm> and <Pr, Qr>");

      var newRoot = (CompilationUnitSyntax)newTree.GetRoot();
      if (newRoot.ContainsDiagnostics) {
        Utils.Trace("Aborting: the new tree has syntax errors");

        return null;
      }

      // Let Clousot see the rewritten unit
      var connectionToClousot = new RoslynToCCICodeModel.ClousotGlue();

      var results = connectionToClousot.AnalyzeMeAUnit(newLocalDocument, newRoot, cancellationToken, this.options,
        new string[] { "-extractmethodmoderefine", newExtractedMethod.Identifier.ValueText, "-premode", "combined", "-suggest", "methodensures", "-suggest:requires" });

      if (results == null) return null;

      foreach (var result in results)
      {
        cancellationToken.ThrowIfCancellationRequested();

        Utils.Trace("Getting Clousot Result");

        String condition;
        ContractKind kind;
        if (result.Message.TryParseSuggestion(out kind, out condition)) {
          Utils.Trace("Inserting Clousot result. New Condition: " + condition);

          // Parse the condition
          var newContract = SyntaxFactory.ParseStatement(condition + Environment.NewLine);

          if (!newContract.ContainsDiagnostics) {
            newExtractedMethod = newExtractedMethod.InsertStatements(newContract, kind);
          } else {
            Utils.Trace("\tskipped, as it contains syntax errors");
          }
        }
      }

      return newExtractedMethod;
    }
    private MethodDeclarationSyntax ExtractAndAddPsQs(ref CancellationToken cancellationToken, Microsoft.CodeAnalysis.Document localDocument, CompilationUnitSyntax newRoot, MethodDeclarationSyntax newExtractedMethod)
    {
      // Let Clousot see the rewritten unit

      var connectionToClousot = new RoslynToCCICodeModel.ClousotGlue();
      var results = connectionToClousot.AnalyzeMeAUnit(localDocument, newRoot, cancellationToken, this.options,
        new string[] { "-extractmethodmode", "-arrays:arraypurity", "-suggest:requires" /*"-memberNameSelect",*/ });
      if (results == null) return null;
      foreach (var result in results)
      {
        cancellationToken.ThrowIfCancellationRequested();
        Utils.Trace("Getting Clousot Result");

        String condition;
        ContractKind kind;
        if (result.IsExtractMethodSuggestion && result.Message.TryParseSuggestion(out kind, out condition))
        {
          Utils.Trace("Inserting Clousot result. New Condition: " + condition);

          // Parse the condition
          var newContract = SyntaxFactory.ParseStatement(condition + Environment.NewLine);

          newExtractedMethod = newExtractedMethod.InsertStatements(newContract, kind);
        }
        else
        {
          Utils.Trace("Skipped Clousot output : " + result.Message);
        }
      }

      return newExtractedMethod;
    }
예제 #5
0
        private IEnumerable <SearchResult> DoTheWorkToSearchTheCallers(string query)
        {
            // We should move this in the UI
            var selectionStart = this.wpfTextView.Selection.Start.Position.Position;
            var selectionEnd   = this.wpfTextView.Selection.End.Position.Position;

            var results = new List <SearchResult>();

            if (selectionStart == selectionEnd)
            {
                Trace.WriteLine(string.Format("Selection: {0}", selectionStart));

                var       container = wpfTextView.TextBuffer.AsTextContainer();
                Workspace workspace;
                Workspace.TryGetWorkspace(container, out workspace);

                if (workspace != null)
                {
                    Document doc;
                    var      docIds = workspace.GetRelatedDocumentIds(container);
                    if (docIds.Any())
                    {
                        var docId = docIds.First();
                        doc = Helper.OpenDocument(workspace, docId);
                        var span       = new Microsoft.CodeAnalysis.Text.TextSpan(selectionStart, 0);
                        var syntaxNode = doc.GetSyntaxTree().GetRoot() as SyntaxNode;
                        if (syntaxNode != null)
                        {
                            var methodFinder = EnclosingMethodFinder.GetMethodSpans(syntaxNode);
                            BaseMethodDeclarationSyntax method;
                            if (methodFinder.TryGetValueContainingSpan(span, out method))
                            {
                                // Add the precondition
                                var preAsStr  = string.Format(CLOUSOT_QUERY_PRECONDITION, query);
                                var pre       = SyntaxFactory.ParseStatement(preAsStr + Environment.NewLine + Environment.NewLine); // F: adding two newlines as Roslyn for some reason pretty print the text in a different way, and loses one line at the end of the file
                                var newMethod = method.InsertStatements(pre, ContractKind.Precondition);
                                var newRoot   = ((SyntaxNode)doc.GetSyntaxTree().GetRoot()).ReplaceNode(method, newMethod);

                                // Create the new Roslyn environment
                                var newSolution = doc.Project.Solution.WithDocumentText(doc.Id, newRoot.GetText());
                                //var newSolution = doc.Project.Solution.UpdateDocument(doc.Id, newRoot.GetText());
                                var locDocument = newSolution.GetDocument(doc.Id);
                                var newTree     = (CompilationUnitSyntax)locDocument.GetSyntaxTree().GetRoot();

                                try
                                {
                                    Trace.WriteLine(string.Format("Annotated tree for the state:\n{0}", newRoot.GetText()));

                                    var run = new RoslynToCCICodeModel.ClousotGlue().AnalyzeMeAUnit(locDocument,
                                                                                                    newTree,
                                                                                                    new System.Threading.CancellationToken(),
                                                                                                    this.options,
                                                                                                    new string[] { "-warnscores:false", "-sortwarns:false", "-suggest:!!", "-show", "validations" },
                                                                                                    false
                                                                                                    );
                                    if (run == null)
                                    {
                                        return(new SearchResult[0]);
                                    }

                                    var fullString           = preAsStr + Environment.NewLine;
                                    var injectedPrecondition = newRoot.DescendantNodes().OfType <StatementSyntax>().Where(s => s.GetText().ToString().Equals(fullString)).FirstOrDefault();
                                    if (injectedPrecondition == null)
                                    {
                                        return(new SearchResult[0]);
                                    }
                                    var injectedPreconditionSpan = injectedPrecondition.Span;
                                    var newCodeIsBiggerBy        = newMethod.FullSpan.Length - method.FullSpan.Length;

                                    foreach (var r in run)
                                    {
                                        Trace.WriteLine(string.Format("{0}: {1}", r.Message, r.outcome));

                                        if (r.outcome.HasValue && // it is not a suggestion
                                            r.startPoint != null &&
                                            r.RelatedLocationsWithSourceContext != null &&
                                            r.RelatedLocationsWithSourceContext.Count() == 1 && // Guess: we want to have to only related to be our new contract
                                            r.Message.Contains("requires")                      // HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK : We should understand why sometimes r.RelatedLocationsWithSourceContext.Count() == 1, but the proof obligation is a non-null. From debugger seems that the related pc is the same as the original
                                            )
                                        {
                                            var pc         = r.RelatedLocationsWithSourceContext.First();
                                            var startIndex = pc.Block.SourceStartIndex(pc);
                                            var length     = pc.Block.SourceLength(pc);

                                            if (!injectedPreconditionSpan.Contains(new Microsoft.CodeAnalysis.Text.TextSpan(startIndex, length)))
                                            {
                                                continue;
                                            }

                                            // But if the pc is after the injected precondition, then need to substract off the
                                            // length of the injected text from the start position
                                            var realSpan = (r.Span.Start < startIndex) ? r.Span : new Microsoft.CodeAnalysis.Text.TextSpan(r.Span.Start - newCodeIsBiggerBy, r.Span.Length);

                                            //BaseMethodDeclarationSyntax caller;
                                            var loc    = doc.GetSyntaxTree().GetLocation(realSpan);
                                            var caller = syntaxNode.DescendantNodes().OfType <MethodDeclarationSyntax>().Where(m => m.Span.Contains(realSpan)).FirstOrDefault();

                                            if (caller != null)
                                            {
                                                var startLine   = doc.GetSyntaxTree().GetLineSpan(realSpan, true).StartLinePosition.Line + 1;
                                                var startColumn = doc.GetSyntaxTree().GetLineSpan(realSpan, true).StartLinePosition.Character + 1;
                                                results.Add(new SearchResult(startLine, startColumn, caller, r.outcome.Value));
                                            }
                                            else
                                            {
                                                Trace.WriteLine("Failed to find the containing method");
                                            }
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    Trace.WriteLine(string.Format("Some exception was thrown inside Clousot...\nDetails:\n{0}", e.ToString()));
                                }
                            }
                        }
                    }
                }
            }
            return(results);
        }
예제 #6
0
        // TODO: refactor this code to share with DoTheWork
        private string DoTheWorkToInferInvariants()
        {
            // We should move this in the UI
            var selectionStart = this.wpfTextView.Selection.Start.Position.Position;
            var selectionEnd   = this.wpfTextView.Selection.End.Position.Position;

            if (selectionStart == selectionEnd)
            {
                Trace.WriteLine(string.Format("Selection: {0}", selectionStart));

                var container = wpfTextView.TextBuffer.AsTextContainer();
                //var text = wpfTextView.TextBuffer.CurrentSnapshot.AsText();
                Workspace workspace;
                Workspace.TryGetWorkspace(container, out workspace);
                //var workspaceDiscovery = Helper.GetMefService<IWorkspaceDiscoveryService>();
                //var workspace = workspaceDiscovery.GetWorkspace(container);

                if (workspace != null)
                {
                    Document doc;
                    var      docIds = workspace.GetRelatedDocumentIds(container);
                    if (docIds.Any())
                    {
                        var docId = docIds.First();
                        doc = Helper.OpenDocument(workspace, docId);
                        var syntax = doc.GetSyntaxTree();
                        var source = syntax.GetText().ToString();

                        // Generate the new text
                        var newText = GenerateAdornedSource(doc, selectionStart);

                        var newSolution = doc.Project.Solution.WithDocumentText(doc.Id, SourceText.From(newText));
                        //var newSolution = doc.Project.Solution.UpdateDocument(doc.Id, StringText.From(newText));
                        var locDocument = newSolution.GetDocument(doc.Id);
                        var newTree     = (CompilationUnitSyntax)locDocument.GetSyntaxTree().GetRoot();

                        if (!newTree.ContainsDiagnostics)
                        {
                            try
                            {
                                Trace.WriteLine(string.Format("Annotated tree for the state:\n{0}", newText));

                                var clousotConnection = new RoslynToCCICodeModel.ClousotGlue();
                                var run = clousotConnection.AnalyzeMeAUnit(locDocument,
                                                                           newTree,
                                                                           new System.Threading.CancellationToken(),
                                                                           this.options,
                                                                           new string[] { "-warnscores:false", "-sortwarns:false", "-suggest:!!", "-invariantsuggestmode:true" },
                                                                           true // we want to filter all the messages but the answer of Clousot
                                                                           );
                                if (run == null)
                                {
                                    return(null);
                                }
                                foreach (var r in run)
                                {
                                    Trace.WriteLine(string.Format("{0}: {1}", r.Message, r.outcome));

                                    if (r.IsInvariantAtSuggestion)
                                    {
                                        return(PrettyFormat(r.Message));
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                Trace.WriteLine(string.Format("Some exception was thrown inside Clousot...\nDetails:\n{0}", e.ToString()));
                            }
                        }
                        else
                        {
                            Trace.WriteLine("Compilation error from Roslyn");
                        }
                    }
                }
            }
            else
            {
                Trace.WriteLine(string.Format("start/end do not match {0} {1}", selectionStart, selectionEnd));
            }

            return(null);
        }
예제 #7
0
        private ProofOutcome?DoTheWork(string query, IEnumerable <CodeAssumption> assumptions)
        {
            // We should move this in the UI
            var selectionStart = this.wpfTextView.Selection.Start.Position.Position;
            var selectionEnd   = this.wpfTextView.Selection.End.Position.Position;

            if (selectionStart == selectionEnd)
            {
                Trace.WriteLine(string.Format("Selection: {0}", selectionStart));

                var container = wpfTextView.TextBuffer.AsTextContainer();
                //var text = wpfTextView.TextBuffer.CurrentSnapshot.AsText();
                Workspace workspace;
                Workspace.TryGetWorkspace(container, out workspace);
                //var workspaceDiscovery = Helper.GetMefService<IWorkspaceDiscoveryService>();
                //var workspace = workspaceDiscovery.GetWorkspace(container);

                if (workspace != null)
                {
                    Document doc;
                    var      docIds = workspace.GetRelatedDocumentIds(container);
                    if (docIds.Any())
                    {
                        var docId = docIds.First();
                        doc = Helper.OpenDocument(workspace, docId);
                        var syntax = doc.GetSyntaxTree();
                        var source = syntax.GetText().ToString();

                        var newText = GenerateInstrumentedSourceText(query, assumptions, selectionStart, source);

                        var newSolution = doc.Project.Solution.WithDocumentText(doc.Id, SourceText.From(newText));
                        //var newSolution = doc.Project.Solution.UpdateDocument(doc.Id, StringText.From(newText));
                        var locDocument   = newSolution.GetDocument(doc.Id);
                        var newTree       = (Microsoft.CodeAnalysis.CSharp.Syntax.CompilationUnitSyntax)locDocument.GetSyntaxTree().GetRoot();
                        var adornedSource = GenerateAdornedSource(doc, selectionStart);

                        if (!newTree.ContainsDiagnostics)
                        {
                            try
                            {
                                var clousotConnection = new RoslynToCCICodeModel.ClousotGlue();
                                var run = clousotConnection.AnalyzeMeAUnit(locDocument,
                                                                           newTree,
                                                                           new System.Threading.CancellationToken(),
                                                                           this.options,
                                                                           new string[] { "-warnscores:false", "-sortwarns:false", "-show:validations", "-show:unreached" },
                                                                           true // we want to filter all the messages but the answer of Clousot
                                                                           );
                                if (run == null)
                                {
                                    return(null);
                                }

                                foreach (var r in run)
                                {
                                    Trace.WriteLine(string.Format("{0}: {1}", r.Message, r.outcome));

                                    // if we have a non-null, then this is the outcome
                                    // We can have outcome == null for e.g., suggestions.
                                    // In this case we simply ignore them
                                    if (r.outcome.HasValue)
                                    {
                                        return(r.outcome);
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                Trace.WriteLine(string.Format("Some exception was thrown inside Clousot...\nDetails:\n{0}", e.ToString()));
                            }
                        }
                        else
                        {
                            Trace.WriteLine("Compilation error from Roslyn");
                        }
                    }
                }
            }
            else
            {
                Trace.WriteLine(string.Format("start/end do not match {0} {1}", selectionStart, selectionEnd));
            }

            return(null);
        }
예제 #8
0
        private IEnumerable <SearchResult> DoTheWorkToSearchTheCallers(string query)
        {
            // We should move this in the UI
            var selectionStart = this.wpfTextView.Selection.Start.Position.Position;
            var selectionEnd   = this.wpfTextView.Selection.End.Position.Position;

            var results = new List <SearchResult>();

            if (selectionStart == selectionEnd)
            {
                Trace.WriteLine(string.Format("Selection: {0}", selectionStart));

                var             container = wpfTextView.TextBuffer.AsTextContainer();
                EditorWorkspace workspace;
                EditorWorkspace.TryGetWorkspace(container, out workspace);

                if (workspace != null)
                {
                    Document   doc;
                    DocumentId docId;
                    if (workspace.TryGetDocumentId(container, out docId))
                    {
                        doc = Helper.OpenDocument(workspace, docId);
                        var span       = new Microsoft.CodeAnalysis.Text.TextSpan(selectionStart, 0);
                        var syntaxNode = doc.GetSyntaxTree().GetRoot() as SyntaxNode;
                        if (syntaxNode != null)
                        {
                            var methodFinder = EnclosingMethodFinder.GetMethodSpans(syntaxNode);
                            BaseMethodDeclarationSyntax method;
                            if (methodFinder.TryGetValueContainingSpan(span, out method))
                            {
                                // Add the precondition
                                var preAsStr  = string.Format(CLOUSOT_QUERY_PRECONDITION, query);
                                var pre       = SyntaxFactory.ParseStatement(preAsStr + Environment.NewLine + Environment.NewLine); // F: adding two newlines as Roslyn for some reason pretty print the text in a different way, and loses one line at the end of the file
                                var newMethod = method.InsertStatements(pre, ContractKind.Precondition);
                                var newRoot   = ((SyntaxNode)doc.GetSyntaxTree().GetRoot()).ReplaceNode(method, newMethod);

                                // Create the new Roslyn environment
                                var newSolution = doc.Project.Solution.WithDocumentText(doc.Id, new StringText(newRoot.GetText().ToString()));
                                //var newSolution = doc.Project.Solution.UpdateDocument(doc.Id, new StringText(newRoot.GetText()));
                                var locDocument = newSolution.GetDocument(doc.Id);
                                var newTree     = (CompilationUnitSyntax)locDocument.GetSyntaxTree().GetRoot();

                                try
                                {
                                    Trace.WriteLine(string.Format("Annotated tree for the state:\n{0}", newRoot.GetText()));

                                    var run = new RoslynToCCICodeModel.ClousotGlue().AnalyzeMeAUnit(locDocument,
                                                                                                    newTree,
                                                                                                    new System.Threading.CancellationToken(),
                                                                                                    this.options,
                                                                                                    new string[] { "-warnscores:false", "-sortwarns:false", "-suggest:!!", "-show", "validations" },
                                                                                                    false
                                                                                                    );

                                    foreach (var r in run)
                                    {
                                        Trace.WriteLine(string.Format("{0}: {1}", r.Message, r.outcome));

                                        if (r.outcome.HasValue &&                                                 // it is not a suggestion
                                            r.startPoint != null &&
                                            r.Message.Contains("Contract.Requires") && r.Message.Contains(query)) // we should do better than chekcing the string. This is very weak
                                        {
                                            BaseMethodDeclarationSyntax caller;
                                            if (methodFinder.TryGetValueContainingSpan(r.Span, out caller))
                                            {
                                                var pair = r.startPoint;
                                                results.Add(new SearchResult(pair.Item1, pair.Item2, caller, r.outcome.Value));
                                            }
                                            else
                                            {
                                                Trace.WriteLine("Failed to find the containing method");
                                            }
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    Trace.WriteLine(string.Format("Some exception was thrown inside Clousot...\nDetails:\n{0}", e.ToString()));
                                }
                            }
                        }
                    }
                }
            }
            return(results.Distinct());
        }