/// <summary> /// Prints all the diagnostics generated by the compilation /// </summary> /// <param name="compilation"></param> internal static void PrintDiagnostics(IEnumerable <Diagnostic> diagnostics) { #region CodeContracts Contract.Requires(diagnostics != null); #endregion CodeContracts var errors = diagnostics.Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error); //errors = errors.Where(error => error.Id != "CS7027"); RBLogger.Indent(); foreach (var d in errors.Where(error => error.Location.SourceTree == null)) { RBLogger.Info(d); } RBLogger.Unindent(); errors = errors.Where(error => error.Location.SourceTree != null); foreach (var filegroup in errors.GroupBy(error => error.Location.SourceTree.FilePath)) { var first = filegroup.First(); RBLogger.Info(first.Location.SourceTree.FilePath); RBLogger.Indent(); foreach (var d in filegroup) { RBLogger.Info(d); } RBLogger.Unindent(); } }
private static void DebugParsing(IEnumerable <BaseAnnotation> annotations) { var total_sugs = 0; foreach (var filegroup in annotations.GroupBy(x => x.FileName)) { if (filegroup.Any()) { RBLogger.Info("Annotations for file " + filegroup.First()); RBLogger.Indent(); foreach (var methodgroup in filegroup.GroupBy(x => x.MethodName)) { if (methodgroup.Any()) { RBLogger.Info("Annotations for method " + methodgroup.First().MethodName); RBLogger.Indent(); foreach (var sug in methodgroup) { total_sugs++; RBLogger.Info(sug.Annotation); } } RBLogger.Unindent(); } RBLogger.Unindent(); } } RBLogger.Info("Total suggestions: {0}", total_sugs); }
private SyntaxNode ComputeReplacement(SyntaxNode old1, SyntaxNode old2) { // old1 is the original node in the tree // old2 is the (potentially) modified version of old1 // that is, old1 is in dict_old_to_new but old2 wont be // if any of its chilrden have been modified if (dict_old_to_new.Keys.Contains(old1)) // this check is redundant? { switch (old2.CSharpKind()) { case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.ConstructorDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.AddAccessorDeclaration: // who knew this was a thing? maybe this will work case SyntaxKind.RemoveAccessorDeclaration: // who knew this was a thing? maybe this will work //Console.WriteLine("Replacing {0} with {1}", old2, dict_old_to_new[old2]); return(dict_old_to_new[old2]); default: RBLogger.Error("Unhandled syntax node kind {0}", old2.CSharpKind()); break; } } return(old2); // don't replace }
private bool CheckRequiredArguments(ref string why) { #region CodeContracts Contract.Ensures(!Contract.Result <bool>() || this.ClousotXML != null); Contract.Ensures(!Contract.Result <bool>() || this.Project != null); Contract.Ensures(!Contract.Result <bool>() || this.Solution != null); Contract.Ensures(!Contract.Result <bool>() || this.Output != OutputOption.unintialized); // I have to think about this: //Contract.Ensures(Contract.Result<bool>() ^ !((this.Output == OutputOption.git && this.GitRoot == null) ^ this.Output == OutputOption.inplace)); #endregion CodeContracts // I'm not positive this is correct: //Contract.Ensures(Contract.Result<bool>() == false || (this.Output != OutputOption.git && this.GitRoot != null) || this.Output != OutputOption.inplace); // right now, only support all options provided var ok = this.ClousotXML != null && this.Project != null && this.Solution != null && this.Output != OutputOption.unintialized; if (!ok) { why = "You need to specify all of: Clousot XML, Project, Solution, output"; RBLogger.Error(why); } var ok2 = (this.Output == OutputOption.git && this.GitRoot != null) ^ this.Output == OutputOption.inplace; if (!ok2) { why = "You need to either: (1) give -output git -gitroot <some_path> (2) give -output inplace but not both"; RBLogger.Error(why); } return(ok & ok2); }
internal static void PrintUsage(string error = null) { if (error != null) { RBLogger.Error("Error in parsing the command line: {0}", error); } RBLogger.Error("USAGE: $ ReviewBot.exe <cccheckoutput.xml> -project <projectfile> -solution <solutionfile> -output [inplace|git -gitroot <gitdirectory>]"); }
public static ReplacementDictionary PrecomputeReplacementNodes(SyntaxDictionary annotationsByNode, Compilation compilation) { #region CodeContracts Contract.Requires(annotationsByNode != null); Contract.Requires(compilation != null); Contract.Ensures(Contract.Result <ReplacementDictionary>() != null); #endregion CodeContracts Output.WriteLine("Precomputing the replacement nodes"); //GetContractRequiresSymbols(comp); var newdict = new ReplacementDictionary(); foreach (var oldkvp in annotationsByNode) { var oldsubdict = oldkvp.Value; var oldfile = oldkvp.Key; var newsubdict = new Dictionary <SyntaxNode, SyntaxNode>(); if (!oldsubdict.Any()) { continue; /* TODO is this right? we have a node with no annotations? */ } SemanticModel = compilation.GetSemanticModel(oldsubdict.First().Key.SyntaxTree); Compilation = compilation; foreach (var oldnode in oldsubdict.Keys) { switch (oldnode.CSharpKind()) { case SyntaxKind.MethodDeclaration: case SyntaxKind.ConstructorDeclaration: case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.AddAccessorDeclaration: // who knew this was a thing? maybe this will work case SyntaxKind.RemoveAccessorDeclaration: // who knew this was a thing? maybe this will work //var oldmethod = oldnode as BaseMethodDeclarationSyntax; //var newmethod = PrecomputeNewMethod(oldmethod, oldsubdict[oldnode]); //if (oldnode.GetText().ToString().Contains("ObjectInvariant")) { int x; } var newmethod = PrecomputeNewMethod(oldnode, oldsubdict[oldnode]); newsubdict.Add(oldnode, newmethod); continue; case SyntaxKind.FieldDeclaration: continue; // we don't need to do anything to read only fields at this point default: RBLogger.Error("Unhandled SyntaxNode kind {0}", oldnode.CSharpKind()); // Debug.Assert(false); // unhandled annotation type continue; } } newdict.Add(oldfile, newsubdict); } return(newdict); }
private static void ReplaceStatement(StatementSyntax original, StatementSyntax replacement, IEnumerable <StatementSyntax> requires, IEnumerable <StatementSyntax> ensures, IEnumerable <StatementSyntax> assumes, IEnumerable <StatementSyntax> other, out IEnumerable <StatementSyntax> newrequires, out IEnumerable <StatementSyntax> newensures, out IEnumerable <StatementSyntax> newassumes, out IEnumerable <StatementSyntax> newother) { newassumes = assumes; newrequires = requires; newensures = ensures; newother = other; if (IsEnsures(original)) { newensures = ensures.Select(x => x == original ? replacement : x); } else if (IsRequires(original)) { newrequires = requires.Select(x => x == original ? replacement : x); } else if (IsAssumes(original)) { newassumes = assumes.Select(x => x == original ? replacement : x); } else if (other.Contains(original)) { newother = other.Select(x => x == original ? replacement : x); } else { RBLogger.Error("The original statement should have been an ensure, require, or assume"); Debug.Assert(false); } }
public static SyntaxDictionary GetSyntaxNodeToAnnotationDict(Compilation compilation, IEnumerable <BaseAnnotation> annotations) { #region CodeContracts Contract.Requires(compilation != null); Contract.Requires(annotations != null); Contract.Ensures(Contract.Result <SyntaxDictionary>() != null); #endregion CodeContracts Output.WriteLine("Creating the SyntaxNode to annotations dictionary"); var annotations_by_node = new SyntaxDictionary(); foreach (var st in compilation.SyntaxTrees) { var fp = st.FilePath; var curr_anns = annotations.Where(x => x.FileName.Equals(fp, StringComparison.OrdinalIgnoreCase)); var fields = curr_anns.OfType <ReadonlyField>(); curr_anns = curr_anns.Except(fields); //Dictionary<MethodNameId, List<BaseAnnotation>> curr_anns; //if (annotations.TryGetValue(fp, out curr_anns)) // does the syntax tree have any annotations? if (curr_anns.Any()) { annotations_by_node.Add(fp, new Dictionary <SyntaxNode, List <BaseAnnotation> >()); var sm = compilation.GetSemanticModel(st); var mf = new MethodsFinder(curr_anns, sm); var before = curr_anns.Count(); var after = mf.methods_to_annotate.Count; if (before != after) { Output.WriteWarning("Didn't match all methods for " + fp + " There were " + before + " but now " + after, "ERROR"); Output.WriteLine("Next the list of those we failed to match"); foreach (var orig in curr_anns.Select(x => x.MethodName)) { var matched = false; foreach (var newguy in mf.methods_to_annotate.Keys) { if (newguy is FieldDeclarationSyntax) { continue; } // this way of finding missing annotations doesn't really work for readonly fields var sym = sm.GetDeclaredSymbol(newguy) as ISymbol; var dci = sym.GetDocumentationCommentId(); if (dci.Equals(orig)) { matched = true; } } if (!matched) { Output.WriteLine("Failed to find {0}", orig); } } } else { Output.WriteLine("Matched all methods in {0}", fp); } //before = DictionaryHelpers.CountTotalItems(curr_anns); before = curr_anns.Count(); after = DictionaryHelpers.CountTotalItems(mf.methods_to_annotate); if (before != after) { Output.WriteWarning("Lost some annotations for " + fp + " There were " + before + " but now " + after, "ERROR"); } else { Output.WriteLine("Matched all annotations in {0}", fp); } foreach (var key in mf.methods_to_annotate.Keys) { annotations_by_node[fp].Add(key, mf.methods_to_annotate[key]); } } } int total = 0; foreach (var dict in annotations_by_node.Values) { total += DictionaryHelpers.CountTotalItems(dict); } Output.WriteLine("I started with {0} annotations and I found {1}", annotations.Count().ToString(), total.ToString()); if (annotations.Count() != total) { var interfaces = annotations.OfType <ResolvedInterfaceAnnotation>(); var fields = annotations.OfType <ReadonlyField>(); var invariants = annotations.OfType <ResolvedObjectInvariant>(); var other = annotations.OfType <Precondition>(); var found = new List <BaseAnnotation>(); foreach (var file in annotations_by_node) { foreach (var sugs in file.Value.Values) { found = found.Concat(sugs).ToList(); } } var interfacesFound = found.OfType <ResolvedInterfaceAnnotation>(); var fieldsFound = found.OfType <ReadonlyField>(); var invariantsFound = found.OfType <ResolvedObjectInvariant>(); var otherFound = found.OfType <Precondition>(); RBLogger.Info("Interfaces found {0} of {1}", interfacesFound.Count(), interfaces.Count()); RBLogger.Info("fields found {0} of {1}", fieldsFound.Count(), fields.Count()); RBLogger.Info("invariants found {0} of {1}", invariantsFound.Count(), invariants.Count()); RBLogger.Info("other found {0} of {1}", otherFound.Count(), other.Count()); var lost = other.Except(otherFound); RBLogger.Info("Missing annotations:"); RBLogger.Indent(); foreach (var group in lost.GroupBy(x => x.MethodName)) { RBLogger.Info(group.First().MethodName); RBLogger.Indent(); foreach (var ann in group) { RBLogger.Info(ann); } RBLogger.Unindent(); } RBLogger.Unindent(); //RBLogger.Info("Found annotations {0}", found.Count()); //RBLogger.Info("Unmatched annotations:"); //RBLogger.Indent(); //foreach (var annotation in other) //{ // RBLogger.Info(annotation.MethodName); // RBLogger.Indent(); // RBLogger.Info(annotation); // RBLogger.Unindent(); //} //RBLogger.Unindent(); } return(annotations_by_node); }
/// <summary> /// Get the compilation's errors (ignore warnings, info) /// </summary> /// <param name="compilation">The compilation you want to get the errors for</param> /// <returns></returns> //internal static Dictionary<SyntaxTree, List<Diagnostic>> GetDiagnostics(Compilation compilation) //{ // #region CodeContracts // Contract.Requires(compilation != null); // Contract.Ensures(Contract.Result<Dictionary<SyntaxTree, List<Diagnostic>>>() != null); // #endregion CodeContracts // Contract.Assume(compilation.SyntaxTrees != null); // var diags = new Dictionary<SyntaxTree, List<Diagnostic>>(); // foreach (var st in compilation.SyntaxTrees) // { // //Debug.WriteLine(st.FilePath); // //RBLogger.Info(st.FilePath); // var sm = compilation.GetSemanticModel(st); // var ds = sm.GetDiagnostics(); // foreach (var d in ds) // { // if (d.Severity == DiagnosticSeverity.Error) // { // List<Diagnostic> oldDiagnostics; // if (diags.TryGetValue(st, out oldDiagnostics)) // { // Contract.Assume(oldDiagnostics != null); // this is the semantics of dictionary.TryGetValue right? // oldDiagnostics.Add(d); // } // else // { // diags.Add(st, new List<Diagnostic>()); // diags[st].Add(d); // } // } // } // } // return diags; //} /// <summary> /// Remove the annotations from orig_suggestions that cause diagnostics /// </summary> /// <param name="compilation"></param> /// <param name="origcomp"></param> /// <param name="orig_suggestions"></param> /// <returns></returns> //internal static IEnumerable<BaseAnnotation> FilterBadSuggestions(Compilation newcomp, Compilation origcomp, IEnumerable<BaseAnnotation> orig_suggestions) internal static IEnumerable <BaseAnnotation> FilterBadSuggestions(Compilation compilation, IEnumerable <BaseAnnotation> orig_suggestions) { #region CodeContracts Contract.Requires(compilation != null); Contract.Requires(orig_suggestions != null); Contract.Requires(Contract.ForAll(orig_suggestions, suggestion => suggestion != null)); Contract.Requires(Contract.ForAll(orig_suggestions, suggestion => suggestion.MethodName != null)); Contract.Requires(Contract.ForAll(orig_suggestions, suggestion => suggestion.FileName != null)); #endregion CodeContracts var badSuggestions = new List <BaseAnnotation>(); //foreach (var pair in origcomp.SyntaxTrees.Zip(newcomp.SyntaxTrees, (SyntaxTree a, SyntaxTree b) => Tuple.Create(a,b))) foreach (var syntaxTree in compilation.SyntaxTrees) { var sm = compilation.GetSemanticModel(syntaxTree); var diags = sm.GetDiagnostics(); if (diags.Any()) { var errors = new List <Diagnostic>(); foreach (var d in diags) { if (d.Severity == DiagnosticSeverity.Error) { errors.Add(d); } } if (errors.Any()) { RBLogger.Info("Found the following errors in " + syntaxTree.FilePath + ":"); RBLogger.Indent(); foreach (var e in errors) { RBLogger.Info(e.ToString().Replace(syntaxTree.FilePath, "")); } RBLogger.Unindent(); var thistreessugs = orig_suggestions.Where(x => x.FileName.Equals(syntaxTree.FilePath, StringComparison.OrdinalIgnoreCase)); //Dictionary<MethodNameId, List<BaseAnnotation>> thistreessugs; //if (orig_suggestions.TryGetValue(oldst.FilePath, out thistreessugs)) var dr = new DiagnosticFinder(errors, sm, thistreessugs); dr.Visit(syntaxTree.GetRoot()); //var bad2 = dr.sugs.Where(x => x.isBad); badSuggestions.AddRange(dr.BadSuggestions); RBLogger.ErrorIf(dr.BadSuggestions.Count() != errors.Count(), "Failed to find some bad suggestions in {0}", syntaxTree.FilePath); //Console.WriteLine("bad suggestions:"); //foreach (var b in bad2) { Console.WriteLine(b); } //if (oldst.FilePath.Contains("RuleBuilder")) { Debugger.Break(); } } } } //return FilterDictionary(orig_suggestions); //var good = orig_suggestions.Where(x => !x.isBad); //var bad = orig_suggestions.Where(x => x.isBad); var bad = badSuggestions; var good = orig_suggestions.Except(bad, new AnnotationEqualitiyComparer()); //RBLogger.Info("Suggestions that caused errors: {0}", bad.Count()); //RBLogger.Indent(); //RBLogger.Info("bad count: {0}", bad.Count()); //RBLogger.Info("good count: {0}", good.Count()); //RBLogger.Info("orig count: {0}", orig_suggestions.Count()); //foreach (var b in bad) //{ // RBLogger.Info(b); //} //RBLogger.Unindent(); //var not_found = bad.Except(good, new AnnotationEqualitiyComparer()); //RBLogger.Info("unfound bad suggestions count: {0}", not_found.Count()); //RBLogger.Info("unfound bad suggestions:"); //foreach (var nf in not_found) { RBLogger.Info(nf); } //var goodinv = good.OfType<ObjectInvariant>(); //RBLogger.Indent(); //RBLogger.Info("Good object invariants: {0}", goodinv.Count()); //foreach (var b in goodinv) //{ // RBLogger.Info(b); // if (b.FileName.Contains("RuleBuilder")) { int x; } //} //RBLogger.Unindent(); //RBLogger.Indent(); //RBLogger.Info("Good suggestions: {0}", good.Count()); //foreach (var b in good) //{ // RBLogger.Info(b); //} //RBLogger.Unindent(); return(good); }
private static SyntaxNode PrecomputeNewMethod(SyntaxNode oldmethod, List <BaseAnnotation> anns, bool useRegion = true) { SyntaxList <StatementSyntax> oldstmts; if (oldmethod is BaseMethodDeclarationSyntax) { var casted = oldmethod as BaseMethodDeclarationSyntax; oldstmts = casted.Body.Statements; } else if (oldmethod is AccessorDeclarationSyntax) { var casted = oldmethod as AccessorDeclarationSyntax; oldstmts = casted.Body.Statements; } else { RBLogger.Error("Unhandled syntax node kind {0}", oldmethod.CSharpKind()); } var newstmtlist = SyntaxFactory.Block(); var newObjectInvariants = anns.Where(x => x.Kind == ClousotSuggestion.Kind.ObjectInvariant).Select(x => x.statement_syntax as StatementSyntax); var oldObjectInvariants = oldstmts.Where(IsInvariant); var new_requires = anns.Where(x => x.Kind == ClousotSuggestion.Kind.Requires).Select(x => x.statement_syntax as StatementSyntax); var old_requires = oldstmts.Where(IsRequires); var new_ensures = anns.Where(x => x.Kind == ClousotSuggestion.Kind.Ensures || x.Kind == ClousotSuggestion.Kind.EnsuresNecessary) .Select(x => x.statement_syntax as StatementSyntax); var old_ensures = oldstmts.Where(IsEnsures); var new_assumes = anns.Where(x => x.Kind == ClousotSuggestion.Kind.AssumeOnEntry).Select(x => x.statement_syntax as StatementSyntax); //var old_eveything_else = oldstmts.Where(x => !IsEnsures(x) && !IsRequires(x) && !IsAssumes(x)); //var old_eveything_else = oldstmts.Where(x => !IsEnsures(x) && !IsRequires(x)); //var old_assumes = oldstmts.Where(IsAssumes); var old_assumes_list = new List <StatementSyntax>(); // we only want to consider the old assumes to be the ones at the start of the method // assumes can be anywhere, but its incorrect to move ones that use declared variables foreach (var stmt in oldstmts) { if (IsEnsures(stmt)) { continue; } if (IsRequires(stmt)) { continue; } if (IsAssumes(stmt)) { old_assumes_list.Add(stmt); continue; } break; } var old_assumes = old_assumes_list.AsEnumerable(); var old_eveything_else = oldstmts.Except(old_ensures.Concat(old_requires).Concat(old_assumes)); var objectInvariants = newObjectInvariants.Union(oldObjectInvariants, new ContractEqualityComparer()); //if (objectInvariants.Any()) { Debugger.Break(); } SyntaxTrivia regionStart, regionEnd; regionEnd = regionStart = SyntaxFactory.Comment(""); // a dummy initial value if (useRegion && !objectInvariants.Any()) { if (TryFindContractsRegion(old_requires, old_ensures, old_assumes, out regionStart, out regionEnd)) { var first = oldstmts.First(x => x.GetLeadingTrivia().Contains(regionStart)); //var last = oldstmts.First(x => x.GetTrailingTrivia().Contains(regionEnd)); //var last = oldstmts.First(x => x.GetLeadingTrivia().Contains(regionEnd)); //Console.WriteLine(first.Parent.DescendantTrivia().Contains(regionEnd)); // it seems like the #endregion can be essentially anywhere var statements = oldstmts.Where(x => x.GetLeadingTrivia().Contains(regionEnd) || x.GetTrailingTrivia().Contains(regionEnd)); StatementSyntax last, lastModified; last = lastModified = null; if (oldstmts.Any(x => x.GetLeadingTrivia().Contains(regionEnd))) { last = oldstmts.First(x => x.GetLeadingTrivia().Contains(regionEnd)); var lastTrivia = last.GetLeadingTrivia().Where(x => x != regionEnd); lastModified = last.WithLeadingTrivia(lastTrivia); } else if (oldstmts.Any(x => x.GetTrailingTrivia().Contains(regionEnd))) { last = oldstmts.First(x => x.GetTrailingTrivia().Contains(regionEnd)); var lastTrivia = last.GetTrailingTrivia().Where(x => x != regionEnd); lastModified = last.WithTrailingTrivia(lastTrivia); } else if (first.Parent.DescendantTrivia().Contains(regionEnd)) { oldmethod = first.Parent.Parent.ReplaceTrivia(regionEnd, SyntaxFactory.Comment("")); } var firstTrivia = first.GetLeadingTrivia().Where(x => x != regionStart); var firstModified = first.WithLeadingTrivia(firstTrivia); ReplaceStatement(first, firstModified, old_requires, old_ensures, old_assumes, old_eveything_else, out old_requires, out old_ensures, out old_assumes, out old_eveything_else); if (last != null) { ReplaceStatement(last, lastModified, old_requires, old_ensures, old_assumes, old_eveything_else, out old_requires, out old_ensures, out old_assumes, out old_eveything_else); } } else { var addNewLine = !old_requires.Any() && !old_requires.Any(); GetNewRegionTrivia("CodeContracts", addNewLine, out regionStart, out regionEnd); } } var requires = new_requires.Union(old_requires, new ContractEqualityComparer()); var ensures = new_ensures.Union(old_ensures, new ContractEqualityComparer()); var assumes = new_assumes.Union(old_assumes, new ContractEqualityComparer()); RBLogger.ErrorIf(requires.Count() < new_requires.Count(), "Union deleted some items!?"); RBLogger.ErrorIf(ensures.Count() < new_ensures.Count(), "Union deleted some items!?"); RBLogger.ErrorIf(assumes.Count() < new_assumes.Count(), "Union deleted some items!?"); // Scott: there is some weird case where we get duplicate ensures // I haven't tracked it down // this is for debugging: if (ensures.Count() < new_ensures.Count()) { RBLogger.Info("new ensures:"); RBLogger.Indent(); foreach (var ensure in new_ensures) { RBLogger.Info(ensure); } RBLogger.Unindent(); } //foreach(var r in requires) //{ // Console.WriteLine(r); //} //Console.WriteLine(requires.Count()); // the if x.Any()'s are unnecesary (IMHO) but there is a roslyn bug for // adding an empty StatementSyntax[] to an empty BlockSyntax if (requires.Any()) { newstmtlist = newstmtlist.AddStatements(requires.ToArray()); } if (ensures.Any()) { newstmtlist = newstmtlist.AddStatements(ensures.ToArray()); } if (assumes.Any()) { newstmtlist = newstmtlist.AddStatements(assumes.ToArray()); } if (old_eveything_else.Any()) { newstmtlist = newstmtlist.AddStatements(old_eveything_else.ToArray()); } if (objectInvariants.Any()) { newstmtlist = newstmtlist.AddStatements(objectInvariants.ToArray()); // object invariant methods should only have these, so order doesn't matter } if (useRegion && !objectInvariants.Any()) { var first = newstmtlist.Statements.First(); var oldTrivia = first.GetLeadingTrivia(); var newTrivia = SyntaxFactory.TriviaList(regionStart).Concat(oldTrivia); var firstModified = first.WithLeadingTrivia(newTrivia); newstmtlist = newstmtlist.ReplaceNode(first, firstModified); var index = requires.Count() + ensures.Count() + assumes.Count(); var last = newstmtlist.Statements[index - 1]; oldTrivia = last.GetTrailingTrivia(); newTrivia = oldTrivia.Concat(SyntaxFactory.TriviaList(new[] { regionEnd })); var lastModified = last.WithTrailingTrivia(newTrivia); newstmtlist = newstmtlist.ReplaceNode(last, lastModified); } SyntaxNode newmethod = null; if (oldmethod is MethodDeclarationSyntax) { var casted = oldmethod as MethodDeclarationSyntax; //newmethod = casted.WithBody(newstmtlist); // the awful line below is partly so awful to preserve the trivia around the method newmethod = casted.WithBody(casted.Body.WithStatements(newstmtlist.Statements)); } if (oldmethod is ConstructorDeclarationSyntax) { var casted = oldmethod as ConstructorDeclarationSyntax; //newmethod = casted.WithBody(newstmtlist); newmethod = casted.WithBody(casted.Body.WithStatements(newstmtlist.Statements)); } if (oldmethod is AccessorDeclarationSyntax) { var casted = oldmethod as AccessorDeclarationSyntax; //newmethod = casted.WithBody(newstmtlist); newmethod = casted.WithBody(casted.Body.WithStatements(newstmtlist.Statements)); } //var newmethod = oldmethod is MethodDeclarationSyntax ? (BaseMethodDeclarationSyntax)((MethodDeclarationSyntax)oldmethod).WithBody(newstmtlist) : // (BaseMethodDeclarationSyntax)((ConstructorDeclarationSyntax)oldmethod).WithBody(newstmtlist); //Console.WriteLine("Annotated Method: {0}", newmethod); return(newmethod); }
/// <summary> /// Parse the args into an Option object /// </summary> /// <param name="args">the args param to Main</param> /// <param name="options">the parsed arguements, valid if return is ture</param> /// <param name="why">an error message if parsing fails and the return is false</param> /// <returns>true if parsing succeeded, false otherwise</returns> internal static bool TryParseOptions(string[] args, out Options options, out string why) { #region CodeContracts Contract.Requires(Contract.ForAll(args, arg => arg != null)); Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out options) != null); Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out options).Project != null); Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out options).Solution != null); Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out options).ClousotXML != null); Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out options).Output != OutputOption.unintialized); Contract.Ensures(Contract.Result <bool>() || Contract.ValueAtReturn(out why) != null); // there should be a contract for the output option, but it's complicated //Contract.Ensures( // !Contract.Result<bool>() // || ((Contract.ValueAtReturn(out options).Output == OutputOption.git && Contract.ValueAtReturn(out options).GitRoot != null) // ^ (Contract.ValueAtReturn(out options).Output == OutputOption.inplace)) //); #endregion CodeContracts options = new Options(); why = null; for (var i = 0; i < args.Length; i++) { var arg = args[i]; if (IsOption(arg, out arg)) { switch (arg) { case "project": if (i == args.Length - 1) { why = "The last argument can't be a keyword"; return(false); } options.Project = args[++i]; break; case "source": if (i == args.Length - 1) { why = "The last argument can't be a keyword"; return(false); } options.SourceFile = args[++i]; break; case "break": System.Diagnostics.Debugger.Launch(); break; case "solution": if (i == args.Length - 1) { why = "The last argument can't be a keyword"; return(false); } options.Solution = args[++i]; break; case "output": if (i == args.Length - 1) { why = "The last argument can't be a keyword"; return(false); } OutputOption oo; if (Enum.TryParse(args[++i], true, out oo)) { options.Output = oo; } else { why = "Unrecognized output option: " + args[i]; return(false); } break; case "gitroot": if (i == args.Length - 1) { why = "The last argument can't be a keyword"; return(false); } options.GitRoot = args[++i]; if (!Directory.Exists(options.GitRoot)) { why = "git root directory must exist"; return(false); } break; default: options = null; why = "Unrecognized option " + arg; RBLogger.Error("Invalid option {0}", arg); return(false); } } else { if (options.ClousotXML != null) { why = "Cannot express two (or more) .xml files"; return(false); } else { options.ClousotXML = args[0]; } } } return(options.CheckRequiredArguments(ref why)); }