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; }
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); }
// 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); }
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); }
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()); }