コード例 #1
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);
        }
コード例 #2
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());
        }