private void Visit(AnnotatedCodeLocation annotatedCodeLocation, string annotatedCodeLocationPointer) { Analyze(annotatedCodeLocation, annotatedCodeLocationPointer); if (annotatedCodeLocation.PhysicalLocation != null) { string physicalLocationPointer = annotatedCodeLocationPointer.AtProperty(SarifPropertyName.PhysicalLocation); Visit(annotatedCodeLocation.PhysicalLocation, physicalLocationPointer); } }
protected override void Analyze(AnnotatedCodeLocation annotatedCodeLocation, string annotatedCodeLocationPointer) { var pointer = new JsonPointer(annotatedCodeLocationPointer); JToken token = pointer.Evaluate(Context.InputLogToken); if (token.HasProperty(SarifPropertyName.Importance)) { if (!annotatedCodeLocationPointer.Contains(SarifPropertyName.CodeFlows)) { string importancePointer = annotatedCodeLocationPointer.AtProperty(SarifPropertyName.Importance); LogResult(importancePointer, nameof(RuleResources.SARIF011_Default)); } } }
protected override void Analyze(AnnotatedCodeLocation annotatedCodeLocation, string annotatedCodeLocationPointer) { var pointer = new JsonPointer(annotatedCodeLocationPointer); JToken token = pointer.Evaluate(Context.InputLogToken); if (token.HasProperty(SarifPropertyName.Importance)) { if (!annotatedCodeLocationPointer.Contains(SarifPropertyName.CodeFlows)) { string importancePointer = annotatedCodeLocationPointer.AtProperty(SarifPropertyName.Importance); LogResult(importancePointer, nameof(RuleResources.SARIF011_Default)); } } }
protected override void Analyze(AnnotatedCodeLocation annotatedCodeLocation, string annotatedCodeLocationPointer) { if (annotatedCodeLocation.Id != 0) { string idPointer = annotatedCodeLocationPointer.AtProperty(SarifPropertyName.Id); // Emit a different warning depending on whether or not this annotatedCodeLocation // occurs in a codeFlow, because the "step" property is only meaningful within // a codeFlow. string formatId = annotatedCodeLocationPointer.Contains(SarifPropertyName.CodeFlows) ? nameof(RuleResources.SARIF004_Default) : nameof(RuleResources.SARIF004_OnlyInCodeFlow); LogResult(idPointer, formatId); } }
protected override void Analyze(AnnotatedCodeLocation annotatedCodeLocation, string annotatedCodeLocationPointer) { if (annotatedCodeLocation.Id != 0) { string idPointer = annotatedCodeLocationPointer.AtProperty(SarifPropertyName.Id); // Emit a different warning depending on whether or not this annotatedCodeLocation // occurs in a codeFlow, because the "step" property is only meaningful within // a codeFlow. string formatId = annotatedCodeLocationPointer.Contains(SarifPropertyName.CodeFlows) ? nameof(RuleResources.SARIF004_Default) : nameof(RuleResources.SARIF004_OnlyInCodeFlow); LogResult(idPointer, formatId); } }
private static string MakeDisplayString(CallTreeNode node) { // Use the following preferences for the CallTreeNode text. // 1. AnnotatedCodeLocation.Message // 2. AnnotatedCodeLocation.Snippet // 3. Callee for calls // 4. "Return" for returns // 5. AnnotatedCodeLocation.Kind string text = string.Empty; AnnotatedCodeLocation annotatedLocation = node.Location; if (annotatedLocation != null) { if (!String.IsNullOrEmpty(annotatedLocation.Message)) { text = annotatedLocation.Message; } else if (!String.IsNullOrEmpty(annotatedLocation.Snippet)) { text = annotatedLocation.Snippet.Trim(); } else { switch (annotatedLocation.Kind) { case AnnotatedCodeLocationKind.Call: string callee = annotatedLocation.Target; text = !string.IsNullOrEmpty(callee) ? callee : Resources.UnknownCalleeMessage; break; case AnnotatedCodeLocationKind.CallReturn: text = Resources.ReturnMessage; break; default: if (annotatedLocation.Kind != default(AnnotatedCodeLocationKind)) { text = annotatedLocation.Kind.ToString(); } break; } } } return(text); }
private void Visit(CodeFlow codeFlow, string codeFlowPointer) { Analyze(codeFlow, codeFlowPointer); if (codeFlow.Locations != null) { AnnotatedCodeLocation[] annotatedCodeLocations = codeFlow.Locations.ToArray(); string annotatedCodeLocationsPointer = codeFlowPointer.AtProperty(SarifPropertyName.Locations); for (int i = 0; i < annotatedCodeLocations.Length; ++i) { AnnotatedCodeLocation annotatedCodeLocation = annotatedCodeLocations[i]; string annotatedCodeLocationPointer = annotatedCodeLocationsPointer.AtIndex(i); Visit(annotatedCodeLocation, annotatedCodeLocationPointer); } } }
protected override void Analyze(AnnotatedCodeLocation annotatedCodeLocation, string annotatedCodeLocationPointer) { var pointer = new JsonPointer(annotatedCodeLocationPointer); JToken token = pointer.Evaluate(Context.InputLogToken); if (token.HasProperty(SarifPropertyName.Essential)) { string essentialPointer = annotatedCodeLocationPointer.AtProperty(SarifPropertyName.Essential); // Emit a different warning depending on whether or not this annotatedCodeLocation // occurs in a codeFlow, because the "importance" property is only meaningful within // a codeFlow. string formatId = annotatedCodeLocationPointer.Contains(SarifPropertyName.CodeFlows) ? nameof(RuleResources.SARIF005_Default) : nameof(RuleResources.SARIF005_OnlyInCodeFlow); LogResult(essentialPointer, formatId); } }
protected override void Analyze(AnnotatedCodeLocation annotatedCodeLocation, string annotatedCodeLocationPointer) { var pointer = new JsonPointer(annotatedCodeLocationPointer); JToken token = pointer.Evaluate(Context.InputLogToken); if (token.HasProperty(SarifPropertyName.Essential)) { string essentialPointer = annotatedCodeLocationPointer.AtProperty(SarifPropertyName.Essential); // Emit a different warning depending on whether or not this annotatedCodeLocation // occurs in a codeFlow, because the "importance" property is only meaningful within // a codeFlow. string formatId = annotatedCodeLocationPointer.Contains(SarifPropertyName.CodeFlows) ? nameof(RuleResources.SARIF005_Default) : nameof(RuleResources.SARIF005_OnlyInCodeFlow); LogResult(essentialPointer, formatId); } }
protected virtual void Analyze(AnnotatedCodeLocation annotatedCodeLocation, string annotatedCodeLocationPointer) { }
private void Visit(Result result, string resultPointer) { Analyze(result, resultPointer); if (result.Locations != null) { Location[] locations = result.Locations.ToArray(); string locationsPointer = resultPointer.AtProperty(SarifPropertyName.Locations); for (int i = 0; i < locations.Length; ++i) { Location location = locations[i]; string locationPointer = locationsPointer.AtIndex(i); Visit(location, locationPointer); } } if (result.CodeFlows != null) { CodeFlow[] codeFlows = result.CodeFlows.ToArray(); string codeFlowsPointer = resultPointer.AtProperty(SarifPropertyName.CodeFlows); for (int i = 0; i < codeFlows.Length; ++i) { CodeFlow codeFlow = codeFlows[i]; string codeFlowPointer = codeFlowsPointer.AtIndex(i); Visit(codeFlow, codeFlowPointer); } } if (result.Stacks != null) { Stack[] stacks = result.Stacks.ToArray(); string stacksPointer = resultPointer.AtProperty(SarifPropertyName.Stacks); for (int i = 0; i < stacks.Length; ++i) { Stack stack = stacks[i]; string stackPointer = stacksPointer.AtIndex(i); Visit(stack, stackPointer); } } if (result.RelatedLocations != null) { AnnotatedCodeLocation[] relatedLocations = result.RelatedLocations.ToArray(); string relatedLocationsPointer = resultPointer.AtProperty(SarifPropertyName.RelatedLocations); for (int i = 0; i < relatedLocations.Length; ++i) { AnnotatedCodeLocation relatedLocation = relatedLocations[i]; string relatedLocationPointer = relatedLocationsPointer.AtIndex(i); Visit(relatedLocation, relatedLocationPointer); } } if (result.Fixes != null) { Fix[] fixes = result.Fixes.ToArray(); string fixesPointer = resultPointer.AtProperty(SarifPropertyName.Fixes); for (int i = 0; i < fixes.Length; ++i) { Fix fix = fixes[i]; string fixPointer = fixesPointer.AtIndex(i); Visit(fix, fixPointer); } } }
protected override void Analyze(AnnotatedCodeLocation annotatedCodeLocation, string annotatedCodeLocationPointer) { Analyze(annotatedCodeLocation.Message, annotatedCodeLocationPointer); }
private void ProcessLine(string logFileLine, Result result) { var codeFlow = result.CodeFlows[0]; const int STEP = 0; const int URI = 1; const int LINE = 2; // const int IMPORTANCE = 3; This value not persisted to SARIF const int STATE = 4; const int KIND1 = 5; // When KIND1 == "Atomic" the 6th slot is the // the remainder of the kind id, e.g., Atomic Assigment const int KIND2 = 6; // When KIND1 == "Call" the 6th and 7th slots are: const int CALLER = 6; const int CALLEE = 7; int step; string[] tokens = logFileLine.Split(' '); if (int.TryParse(tokens[STEP], out step)) { // If we find a numeric value as the first token, // this is a general step. Uri uri = null; string uriText = tokens[URI].Trim('"'); if (!uriText.Equals("?", StringComparison.Ordinal)) { if (File.Exists(uriText)) { uriText = Path.GetFullPath(uriText); } uri = new Uri(uriText, UriKind.RelativeOrAbsolute); } // We assume a valid line here. This code will throw if not. int line = int.Parse(tokens[LINE]); string sdvKind = tokens[KIND1]; if (sdvKind.Equals("Atomic", StringComparison.Ordinal)) { // For multipart SDV kinds 'Atomic XXX', we // map using the second value only, e.g, // 'Assignment' or 'Conditional' sdvKind = tokens[KIND2]; } AnnotatedCodeLocationKind kind = ConvertToAnnotatedCodeLocationKind(sdvKind.Trim()); var annotatedCodeLocation = new AnnotatedCodeLocation { Kind = kind, Step = step, Importance = AnnotatedCodeLocationImportance.Unimportant, PhysicalLocation = (uri != null) ? new PhysicalLocation { Uri = uri, Region = new Region { StartLine = line } } : null, }; if (kind == AnnotatedCodeLocationKind.Call) { string extraMsg = tokens[KIND1] + " " + tokens[CALLER] + " " + tokens[CALLEE]; string caller, callee; if (ExtractCallerAndCallee(extraMsg.Trim(), out caller, out callee)) { annotatedCodeLocation.FullyQualifiedLogicalName = caller; annotatedCodeLocation.Target = callee; _callers.Push(caller); } else { Debug.Assert(false); } if (uri == null) { annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Unimportant; } else if (IsHarnessOrRulesFiles(uriText)) { annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Important; } else { annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Essential; } } if (kind == AnnotatedCodeLocationKind.CallReturn) { Debug.Assert(_callers.Count > 0); annotatedCodeLocation.FullyQualifiedLogicalName = _callers.Pop(); } string separatorText = "^====Auto====="; string state = tokens[STATE]; string[] stateTokens = state.Split(new string[] { separatorText }, StringSplitOptions.RemoveEmptyEntries); if (stateTokens.Length > 0) { if (stateTokens.Length == 2) { annotatedCodeLocation.SetProperty("currentDataValues", stateTokens[0]); annotatedCodeLocation.SetProperty("permanentDataValues", stateTokens[1]); } else { Debug.Assert(stateTokens.Length == 1); if (stateTokens[0].StartsWith(separatorText)) { annotatedCodeLocation.SetProperty("permanentDataValues", stateTokens[0]); } else { annotatedCodeLocation.SetProperty("currentDataValues", stateTokens[0]); } } } codeFlow.Locations.Add(annotatedCodeLocation); } else { // This is the defect message. const int LEVEL = 0; string levelText = tokens[LEVEL]; result.Level = ConvertToResultLevel(levelText); // Everything on the line following defect level comprises the message result.Message = logFileLine.Substring(levelText.Length).Trim(); // SDV currently produces 'pass' notifications when // the final line is prefixed with 'Error'. We'll examine // the message text to detect this condition if (result.Message.Contains("is satisfied")) { result.Level = ResultLevel.Pass; } // Finally, populate this result location with the // last observed location in the code flow. IList<AnnotatedCodeLocation> locations = result.CodeFlows[0].Locations; for (int i = locations.Count - 1; i >= 0; --i) { if (locations[i].PhysicalLocation != null) { result.Locations.Add(new Location { ResultFile = locations[i].PhysicalLocation }); break; } } } }
private void ReportInvalidStepValues( AnnotatedCodeLocation[] locations, JArray annotatedCodeLocationArray, string annotatedCodeLocationsPointer) { JObject[] annotatedCodeLocationObjects = annotatedCodeLocationArray.Children<JObject>().ToArray(); for (int i = 0; i < locations.Length; ++i) { // Only report "invalid step value" for locations that actually specify // the "step" property (the value of the Step property in the object // model will be 0 for such steps, which is never valid), because we // already reported the missing "step" properties. if (LocationHasStep(annotatedCodeLocationObjects[i]) && locations[i].Step != i + 1) { string invalidStepPointer = annotatedCodeLocationsPointer .AtIndex(i).AtProperty(SarifPropertyName.Step); LogResult( invalidStepPointer, nameof(RuleResources.SARIF009_InvalidStepValue), (i + 1).ToInvariantString(), (locations[i].Step).ToInvariantString()); } } }
public static Microsoft.Sarif.Viewer.Models.AnnotatedCodeLocationModel ToAnnotatedCodeLocationModel(this AnnotatedCodeLocation location) { AnnotatedCodeLocationModel model = new AnnotatedCodeLocationModel(); if (location.PhysicalLocation != null) { model.Region = location.PhysicalLocation.Region; Uri uri = location.PhysicalLocation.Uri; if (uri != null) { model.FilePath = uri.ToPath(); model.UriBaseId = location.PhysicalLocation.UriBaseId; } } model.Message = location.Message; model.Kind = location.Kind.ToString(); model.LogicalLocation = location.FullyQualifiedLogicalName; if (location.Essential) { model.IsEssential = location.Essential; } else { model.IsEssential = location.Importance == AnnotatedCodeLocationImportance.Essential; } return(model); }
protected override void Analyze(AnnotatedCodeLocation annotatedCodeLocation, string annotatedCodeLocationPointer) { Analyze(annotatedCodeLocation.Message, annotatedCodeLocationPointer); }
private void ParseLocationFromAnalysisInfo(Result result) { CodeFlow codeFlow = result.CodeFlows.First(); int step = 0; _reader.Read(); string lastSnippetId = null; while (!AtEndOf(_strings.AnalysisInfo)) { // Note: SourceLocation is an empty element (it has only attributes), // so we can't call AtStartOfNonEmpty here. if (AtStartOf(_strings.SourceLocation)) { string snippetId = _reader.GetAttribute(_strings.SnippetAttribute); PhysicalLocation physLoc = ParsePhysicalLocationFromSourceInfo(); var acl = new AnnotatedCodeLocation { Step = step++, PhysicalLocation = physLoc }; // Remember the id of the snippet associated with this location. // We'll use it to fill the snippet text when we read the Snippets element later on. if (!String.IsNullOrEmpty(snippetId)) { _aclToSnippetIdDictionary.Add(acl, snippetId); } codeFlow.Locations.Add(acl); // Keep track of the snippet associated with the last location in the // CodeFlow; that's the snippet that we'll associate with the Result // as a whole. lastSnippetId = snippetId; // Step past the empty element. _reader.Read(); } else { _reader.Read(); } } if (codeFlow.Locations.Any()) { result.Locations.Add(new Location { // TODO: Confirm that the traces are ordered chronologically // (so that we really do want to use the last one as the // overall result location). ResultFile = codeFlow.Locations.Last().PhysicalLocation }); if (!String.IsNullOrEmpty(lastSnippetId)) { _resultToSnippetIdDictionary.Add(result, lastSnippetId); } } }
private void GenerateCodeFlows(Defect defect, Result result) { List <SFA> sfas = defect?.Path?.SFAs; if (sfas == null || sfas.Count == 0) { return; } int step = 0; var locations = new List <AnnotatedCodeLocation>(); bool pathUsesKeyEvents = defect.Path.SFAs.Any(x => !string.IsNullOrWhiteSpace(x?.KeyEvent?.Id)); foreach (var sfa in defect.Path.SFAs) { var region = new Region() { StartColumn = sfa.Column + 1, StartLine = sfa.Line }; var uri = new Uri($"{sfa.FilePath}{sfa.FileName}", UriKind.Relative); var fileLocation = new PhysicalLocation(uri: uri, uriBaseId: null, region: region); var annotatedCodeLocation = new AnnotatedCodeLocation { PhysicalLocation = fileLocation, Step = ++step }; if (pathUsesKeyEvents) { if (string.IsNullOrWhiteSpace(sfa.KeyEvent?.Id)) { annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Unimportant; } else { annotatedCodeLocation.SetProperty("keyEventId", sfa.KeyEvent.Id); if (Enum.TryParse(sfa.KeyEvent.Kind, true, out AnnotatedCodeLocationKind kind)) { annotatedCodeLocation.Kind = kind; } if (Enum.TryParse(sfa.KeyEvent.Importance, true, out AnnotatedCodeLocationImportance importance)) { annotatedCodeLocation.Importance = importance; } if (!string.IsNullOrWhiteSpace(sfa.KeyEvent.Message)) { annotatedCodeLocation.Message = sfa.KeyEvent.Message; } } } locations.Add(annotatedCodeLocation); } result.CodeFlows = new List <CodeFlow>() { new CodeFlow { Locations = locations } }; }
private IList <AnnotatedCodeLocation> NormalizeRawMessage(string rawMessage, out string normalizedMessage) { // The rawMessage contains embedded related locations. We need to extract the related locations and reformat the rawMessage without the embedded links. // Example rawMessage // po (coming from [["hbm"|"relative://windows/Core/ntgdi/gre/brushapi.cxx:176:4882:3"],["hbm"|"relative://windows/Core/ntgdi/gre/windows/ntgdi.c:1873:50899:3"],["hbm"|"relative://windows/Core/ntgdi/gre/windows/ntgdi.c:5783:154466:3"]]) may not have been checked for validity before call to vSync. // Example normalizedMessage // po (coming from "hbm") may not have been checked for validity before call to vSync. // Example relatedLocations // relative://windows/Core/ntgdi/gre/brushapi.cxx:176:4882:3 // relative://windows/Core/ntgdi/gre/windows/ntgdi.c:1873:50899:3 // relative://windows/Core/ntgdi/gre/windows/ntgdi.c:5783:154466:3 List <AnnotatedCodeLocation> relatedLocations = null; normalizedMessage = String.Empty; var sb = new StringBuilder(); int index = rawMessage.IndexOf("[["); while (index > -1) { sb.Append(rawMessage.Substring(0, index)); rawMessage = rawMessage.Substring(index + 2); index = rawMessage.IndexOf("]]"); // embeddedLinksText contains the text for one set of embedded links except for the leading '[[' and trailing ']]' // "hbm"|"relative://windows/Core/ntgdi/gre/brushapi.cxx:176:4882:3"],["hbm"|"relative://windows/Core/ntgdi/gre/windows/ntgdi.c:1873:50899:3"],["hbm"|"relative://windows/Core/ntgdi/gre/windows/ntgdi.c:5783:154466:3" string embeddedLinksText = rawMessage.Substring(0, index - 1); // embeddedLinks splits the set of embedded links into invividual links // 1. "hbm"|"relative://windows/Core/ntgdi/gre/brushapi.cxx:176:4882:3" // 2. "hbm"|"relative://windows/Core/ntgdi/gre/windows/ntgdi.c:1873:50899:3" // 3. "hbm"|"relative://windows/Core/ntgdi/gre/windows/ntgdi.c:5783:154466:3" string[] embeddedLinks = embeddedLinksText.Split(new string[] { "],[" }, StringSplitOptions.None); foreach (string embeddedLink in embeddedLinks) { string[] tokens = embeddedLink.Split(new char[] { '\"' }, StringSplitOptions.RemoveEmptyEntries); // save the text portion of the link embeddedLinksText = tokens[0]; string location = tokens[2]; string[] locationTokens = location.Split(':'); relatedLocations = relatedLocations ?? new List <AnnotatedCodeLocation>(); PhysicalLocation physicalLocation; if (locationTokens[0].Equals("file", StringComparison.OrdinalIgnoreCase)) { // Special case for file paths, e.g.: // "IComparable"|"file://C:/Windows/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll:0:0:0:0" physicalLocation = new PhysicalLocation { Uri = new Uri($"{locationTokens[0]}:{locationTokens[1]}:{locationTokens[2]}", UriKind.Absolute), Region = new Region { StartLine = Int32.Parse(locationTokens[3]), Offset = Int32.Parse(locationTokens[4]), Length = Int32.Parse(locationTokens[5]) } }; } else { physicalLocation = new PhysicalLocation { Uri = new Uri(locationTokens[1].Substring(1), UriKind.Relative), UriBaseId = "$srcroot", Region = new Region { StartLine = Int32.Parse(locationTokens[2]), Offset = Int32.Parse(locationTokens[3]), Length = Int32.Parse(locationTokens[4]) } }; } var relatedLocation = new AnnotatedCodeLocation { PhysicalLocation = physicalLocation }; relatedLocations.Add(relatedLocation); } // Re-add the text portion of the link. sb.Append("\"" + embeddedLinksText + "\""); rawMessage = rawMessage.Substring(index + "]]".Length); index = rawMessage.IndexOf("[["); } sb.Append(rawMessage); normalizedMessage = sb.ToString(); return(relatedLocations); }
private void ProcessLine(string logFileLine, Result result) { var codeFlow = result.CodeFlows[0]; const int STEP = 0; const int URI = 1; const int LINE = 2; // const int IMPORTANCE = 3; This value not persisted to SARIF const int STATE = 4; const int KIND1 = 5; // When KIND1 == "Atomic" the 6th slot is the // the remainder of the kind id, e.g., Atomic Assigment const int KIND2 = 6; // When KIND1 == "Call" the 6th and 7th slots are: const int CALLER = 6; const int CALLEE = 7; int step; string[] tokens = logFileLine.Split(' '); if (int.TryParse(tokens[STEP], out step)) { // If we find a numeric value as the first token, // this is a general step. Uri uri = null; string uriText = tokens[URI].Trim('"'); if (!uriText.Equals("?", StringComparison.Ordinal)) { if (File.Exists(uriText)) { uriText = Path.GetFullPath(uriText); } uri = new Uri(uriText, UriKind.RelativeOrAbsolute); } // We assume a valid line here. This code will throw if not. int line = int.Parse(tokens[LINE]); string sdvKind = tokens[KIND1]; if (sdvKind.Equals("Atomic", StringComparison.Ordinal)) { // For multipart SDV kinds 'Atomic XXX', we // map using the second value only, e.g, // 'Assignment' or 'Conditional' sdvKind = tokens[KIND2]; } AnnotatedCodeLocationKind kind = ConvertToAnnotatedCodeLocationKind(sdvKind.Trim()); var annotatedCodeLocation = new AnnotatedCodeLocation { Kind = kind, Step = step, Importance = AnnotatedCodeLocationImportance.Unimportant, PhysicalLocation = (uri != null) ? new PhysicalLocation { Uri = uri, Region = new Region { StartLine = line } } : null, }; if (kind == AnnotatedCodeLocationKind.Call) { string extraMsg = tokens[KIND1] + " " + tokens[CALLER] + " " + tokens[CALLEE]; string caller, callee; if (ExtractCallerAndCallee(extraMsg.Trim(), out caller, out callee)) { annotatedCodeLocation.FullyQualifiedLogicalName = caller; annotatedCodeLocation.Target = callee; _callers.Push(caller); } else { Debug.Assert(false); } if (uri == null) { annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Unimportant; } else if (IsHarnessOrRulesFiles(uriText)) { annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Important; } else { annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Essential; } } if (kind == AnnotatedCodeLocationKind.CallReturn) { Debug.Assert(_callers.Count > 0); annotatedCodeLocation.FullyQualifiedLogicalName = _callers.Pop(); } string separatorText = "^====Auto====="; string state = tokens[STATE]; string[] stateTokens = state.Split(new string[] { separatorText }, StringSplitOptions.RemoveEmptyEntries); if (stateTokens.Length > 0) { if (stateTokens.Length == 2) { annotatedCodeLocation.SetProperty("currentDataValues", stateTokens[0]); annotatedCodeLocation.SetProperty("permanentDataValues", stateTokens[1]); } else { Debug.Assert(stateTokens.Length == 1); if (stateTokens[0].StartsWith(separatorText)) { annotatedCodeLocation.SetProperty("permanentDataValues", stateTokens[0]); } else { annotatedCodeLocation.SetProperty("currentDataValues", stateTokens[0]); } } } codeFlow.Locations.Add(annotatedCodeLocation); } else { // This is the defect message. const int LEVEL = 0; string levelText = tokens[LEVEL]; result.Level = ConvertToResultLevel(levelText); // Everything on the line following defect level comprises the message result.Message = logFileLine.Substring(levelText.Length).Trim(); // SDV currently produces 'pass' notifications when // the final line is prefixed with 'Error'. We'll examine // the message text to detect this condition if (result.Message.Contains("is satisfied")) { result.Level = ResultLevel.Pass; } // Finally, populate this result location with the // last observed location in the code flow. IList <AnnotatedCodeLocation> locations = result.CodeFlows[0].Locations; for (int i = locations.Count - 1; i >= 0; --i) { if (locations[i].PhysicalLocation != null) { result.Locations.Add(new Location { ResultFile = locations[i].PhysicalLocation }); break; } } } }