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