private static string MakeDisplayString(CallTreeNode node) { // Use the following preferences for the CallTreeNode text. // 1. CodeFlowLocation.Location.Message.Text // 2. CodeFlowLocation.Location.PhysicalLocation.Region.Snippet.Text // 3. "Continuing" string text = string.Empty; CodeFlowLocation codeFlowLocation = node.Location; if (codeFlowLocation != null) { if (!String.IsNullOrWhiteSpace(codeFlowLocation.Location?.Message?.Text)) { text = codeFlowLocation.Location.Message.Text; } else if (!String.IsNullOrWhiteSpace(codeFlowLocation.Location?.PhysicalLocation?.Region?.Snippet?.Text)) { text = codeFlowLocation.Location.PhysicalLocation.Region.Snippet.Text.Trim(); } else { text = Resources.ContinuingCallTreeNodeMessage; } } return(text); }
internal CodeFlowLocation CreateCodeFlowLocation(AnnotatedCodeLocationVersionOne v1AnnotatedCodeLocation) { CodeFlowLocation codeFlowLocation = null; if (v1AnnotatedCodeLocation != null) { codeFlowLocation = new CodeFlowLocation { Importance = Utilities.CreateCodeFlowLocationImportance(v1AnnotatedCodeLocation.Importance), Location = CreateLocation(v1AnnotatedCodeLocation), Module = v1AnnotatedCodeLocation.Module, NestingLevel = _codeFlowLocationNestingLevel, Properties = v1AnnotatedCodeLocation.Properties, State = v1AnnotatedCodeLocation.State, Step = v1AnnotatedCodeLocation.Step + _codeFlowLocationStepAdjustment }; if (v1AnnotatedCodeLocation.Kind == AnnotatedCodeLocationKindVersionOne.Call) { _codeFlowLocationNestingLevel++; } else if (v1AnnotatedCodeLocation.Kind == AnnotatedCodeLocationKindVersionOne.CallReturn) { _codeFlowLocationNestingLevel--; } } return(codeFlowLocation); }
public static CodeFlowLocationModel ToCodeFlowLocationModel(this CodeFlowLocation codeFlowLocation) { var model = codeFlowLocation.Location != null ? codeFlowLocation.Location.ToCodeFlowLocationModel() : new CodeFlowLocationModel(); model.IsEssential = codeFlowLocation.Importance == CodeFlowLocationImportance.Essential; return(model); }
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 <CodeFlowLocation>(); 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(id: 0, fileLocation: new FileLocation(uri: uri, uriBaseId: null), region: region, contextRegion: null); var codeFlowLocation = new CodeFlowLocation { Location = new Location { PhysicalLocation = fileLocation }, Step = ++step }; if (pathUsesKeyEvents) { if (string.IsNullOrWhiteSpace(sfa.KeyEvent?.Id)) { codeFlowLocation.Importance = CodeFlowLocationImportance.Unimportant; } else { codeFlowLocation.SetProperty("keyEventId", sfa.KeyEvent.Id); if (Enum.TryParse(sfa.KeyEvent.Importance, true, out CodeFlowLocationImportance importance)) { codeFlowLocation.Importance = importance; } if (!string.IsNullOrWhiteSpace(sfa.KeyEvent.Message) && codeFlowLocation.Location?.Message != null) { codeFlowLocation.Location.Message.Text = sfa.KeyEvent.Message; } } } locations.Add(codeFlowLocation); } result.CodeFlows = new List <CodeFlow>() { SarifUtilities.CreateSingleThreadedCodeFlow(locations) }; }
private void ProcessLine(string logFileLine, ref int nestingLevel, 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]; } sdvKind = sdvKind.Trim(); var codeFlowLocation = new CodeFlowLocation { Step = step + 1, Importance = CodeFlowLocationImportance.Unimportant, Location = new Location { Message = new Message() } }; if (uri != null) { codeFlowLocation.Location.PhysicalLocation = new PhysicalLocation { FileLocation = new FileLocation { Uri = uri }, Region = new Region { StartLine = line } }; } if (sdvKind == "Call") { string extraMsg = $"{tokens[KIND1]} {tokens[CALLER]} {tokens[CALLEE]}"; string caller, callee; if (ExtractCallerAndCallee(extraMsg.Trim(), out caller, out callee)) { codeFlowLocation.Location.FullyQualifiedLogicalName = caller; codeFlowLocation.Location.Message.Text = callee; codeFlowLocation.SetProperty("target", callee); _callers.Push(caller); } else { Debug.Assert(false); } codeFlowLocation.NestingLevel = nestingLevel++; if (uri == null) { codeFlowLocation.Importance = CodeFlowLocationImportance.Unimportant; } else if (IsHarnessOrRulesFiles(uriText)) { codeFlowLocation.Importance = CodeFlowLocationImportance.Important; } else { codeFlowLocation.Importance = CodeFlowLocationImportance.Essential; } } else if (sdvKind == "Return") { Debug.Assert(_callers.Count > 0); codeFlowLocation.NestingLevel = nestingLevel--; codeFlowLocation.Location.FullyQualifiedLogicalName = _callers.Pop(); } else { codeFlowLocation.NestingLevel = nestingLevel; codeFlowLocation.Location.Message.Text = sdvKind; } string separatorText = "^====Auto====="; string state = tokens[STATE]; string[] stateTokens = state.Split(new string[] { separatorText }, StringSplitOptions.RemoveEmptyEntries); if (stateTokens.Length > 0) { if (stateTokens.Length == 2) { codeFlowLocation.SetProperty("currentDataValues", stateTokens[0]); codeFlowLocation.SetProperty("permanentDataValues", stateTokens[1]); } else { Debug.Assert(stateTokens.Length == 1); if (stateTokens[0].StartsWith(separatorText)) { codeFlowLocation.SetProperty("permanentDataValues", stateTokens[0]); } else { codeFlowLocation.SetProperty("currentDataValues", stateTokens[0]); } } } codeFlow.ThreadFlows[0].Locations.Add(codeFlowLocation); } 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 = new Message { Text = 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.Text.Contains("is satisfied")) { result.Level = ResultLevel.Pass; } // Finally, populate this result location with the // last observed location in the code flow. IList <CodeFlowLocation> locations = result.CodeFlows[0].ThreadFlows[0].Locations; for (int i = locations.Count - 1; i >= 0; --i) { if (locations[i].Location?.PhysicalLocation != null) { result.Locations.Add(new Location { PhysicalLocation = locations[i].Location.PhysicalLocation }); break; } } } }
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 cfl = new CodeFlowLocation { Step = ++step, Location = new Location { 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)) { _cflToSnippetIdDictionary.Add(cfl, snippetId); } codeFlow.ThreadFlows[0].Locations.Add(cfl); // 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.ThreadFlows[0].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). PhysicalLocation = codeFlow.ThreadFlows[0].Locations.Last().Location?.PhysicalLocation }); if (!String.IsNullOrEmpty(lastSnippetId)) { _resultToSnippetIdDictionary.Add(result, lastSnippetId); } } }