private static bool PreventsSuccessfulDelegateConversion(FirstAmongEqualsSet <Diagnostic> set) { foreach (var diagnostic in set) { if (ErrorFacts.PreventsSuccessfulDelegateConversion((ErrorCode)diagnostic.Code)) { return(true); } } return(false); }
public bool GenerateSummaryErrors(DiagnosticBag diagnostics) { // It is highly likely that "the same" error will be given for two different // bindings of the same lambda but with different values for the parameters // of the error. For example, if we have x=>x.Blah() where x could be int // or string, then the two errors will be "int does not have member Blah" and // "string does not have member Blah", but the locations and errors numbers // will be the same. // // We should first see if there is a set of errors that are "the same" by // this definition that occur in every lambda binding; if there are then // those are the errors we should report. // // If there are no errors that are common to *every* binding then we // can report the complete set of errors produced by every binding. However, // we still wish to avoid duplicates, so we will use the same logic for // building the union as the intersection; two errors with the same code // and location are to be treated as the same error and only reported once, // regardless of how that error is parameterized. // // The question then rears its head: when given two of "the same" error // to report that are nevertheless different in their arguments, which one // do we choose? To the user it hardly matters; either one points to the // right location in source code. But it surely matters to our testing team; // we do not want to be in a position where some small change to our internal // representation of lambdas causes tests to break because errors are reported // differently. // // What we need to do is find a *repeatable* arbitrary way to choose between // two errors; we can for example simply take the one that is lower in alphabetical // order when converted to a string. var equalityComparer = new CommonDiagnosticComparer(); Func <Diagnostic, Diagnostic, int> canonicalComparer = CanonicallyCompareDiagnostics; FirstAmongEqualsSet <Diagnostic> intersection = null; var convBags = from boundLambda in bindingCache.Values select boundLambda.Diagnostics; var retBags = from boundLambda in returnInferenceCache.Values select boundLambda.Diagnostics; var allBags = convBags.Concat(retBags); foreach (ImmutableArray <Diagnostic> bag in allBags) { if (intersection == null) { intersection = new FirstAmongEqualsSet <Diagnostic>(bag, equalityComparer, canonicalComparer); } else { intersection.IntersectWith(bag); } } if (intersection != null) { foreach (var diagnostic in intersection) { if (ErrorFacts.PreventsSuccessfulDelegateConversion((ErrorCode)diagnostic.Code)) { diagnostics.AddRange(intersection); return(true); } } } FirstAmongEqualsSet <Diagnostic> union = null; foreach (ImmutableArray <Diagnostic> bag in allBags) { if (union == null) { union = new FirstAmongEqualsSet <Diagnostic>(bag, equalityComparer, canonicalComparer); } else { union.UnionWith(bag); } } if (union != null) { foreach (var diagnostic in union) { if (ErrorFacts.PreventsSuccessfulDelegateConversion((ErrorCode)diagnostic.Code)) { diagnostics.AddRange(union); return(true); } } } return(false); }