diff --git a/src/Sarif.Converters/AndroidStudioConverter.cs b/src/Sarif.Converters/AndroidStudioConverter.cs index afe13058f..05a47ad92 100644 --- a/src/Sarif.Converters/AndroidStudioConverter.cs +++ b/src/Sarif.Converters/AndroidStudioConverter.cs @@ -6,7 +6,6 @@ using System.Collections.Immutable; using System.Globalization; using System.IO; -using System.Linq; using System.Text; using System.Xml; @@ -59,41 +58,20 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm XmlResolver = null }; - ISet results; + IList results; using (XmlReader xmlReader = XmlReader.Create(input, settings)) { results = ProcessAndroidStudioLog(xmlReader); } - - var tool = new Tool - { - Name = "AndroidStudio" - }; - - var fileInfoFactory = new FileInfoFactory(null, dataToInsert); - Dictionary fileDictionary = fileInfoFactory.Create(results); - + var run = new Run() { - Tool = tool, - ColumnKind = ColumnKind.Utf16CodeUnits + Tool = new Tool { Name = ToolFormat.AndroidStudio }, + ColumnKind = ColumnKind.Utf16CodeUnits, + LogicalLocations = this.LogicalLocations, }; - output.Initialize(run); - - if (fileDictionary != null && fileDictionary.Any()) - { - output.WriteFiles(fileDictionary); - } - - if (LogicalLocations != null && LogicalLocations.Any()) - { - output.WriteLogicalLocations(LogicalLocations); - } - - output.OpenResults(); - output.WriteResults(results); - output.CloseResults(); + PersistResults(output, results, run); } /// Processes an Android Studio log and writes issues therein to an instance of @@ -102,9 +80,9 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm /// /// A list of the objects translated from the AndroidStudio format. /// - private ISet ProcessAndroidStudioLog(XmlReader xmlReader) + private IList ProcessAndroidStudioLog(XmlReader xmlReader) { - var results = new HashSet(Result.ValueComparer); + var results = new List(); int problemsDepth = xmlReader.Depth; xmlReader.ReadStartElement(_strings.Problems); diff --git a/src/Sarif.Converters/ClangAnalyzerConverter.cs b/src/Sarif.Converters/ClangAnalyzerConverter.cs index 140139c8c..aeeef60bf 100644 --- a/src/Sarif.Converters/ClangAnalyzerConverter.cs +++ b/src/Sarif.Converters/ClangAnalyzerConverter.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.IO; using System.Xml; -using Microsoft.CodeAnalysis.Sarif.Writers; namespace Microsoft.CodeAnalysis.Sarif.Converters { @@ -58,27 +57,7 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm } } - var tool = new Tool - { - Name = "Clang" - }; - - var fileInfoFactory = new FileInfoFactory(MimeType.DetermineFromFileExtension, dataToInsert); - Dictionary fileDictionary = fileInfoFactory.Create(results); - - - var run = new Run() - { - Tool = tool - }; - - output.Initialize(run); - - if (fileDictionary != null && fileDictionary.Count > 0) { output.WriteFiles(fileDictionary); } - - output.OpenResults(); - output.WriteResults(results); - output.CloseResults(); + PersistResults(output, results, "Clang Analyzer"); } finally { @@ -155,7 +134,7 @@ private Result CreateResult(IDictionary issueData) int fileNumber = FindInt(location, "file"); if (_files != null && fileNumber < _files.Count) { - fileName = _files[fileNumber] as string; + fileName = (string)_files[fileNumber]; } } diff --git a/src/Sarif.Converters/CppCheckConverter.cs b/src/Sarif.Converters/CppCheckConverter.cs index cdb1ff77a..4227a3f4f 100644 --- a/src/Sarif.Converters/CppCheckConverter.cs +++ b/src/Sarif.Converters/CppCheckConverter.cs @@ -6,8 +6,6 @@ using System.IO; using System.Xml; -using Microsoft.CodeAnalysis.Sarif.Writers; - namespace Microsoft.CodeAnalysis.Sarif.Converters { public class CppCheckConverter : ToolFileConverterBase @@ -114,27 +112,12 @@ private void ProcessCppCheckLog(XmlReader reader, IResultLogWriter output, Optio reader.ReadEndElement(); // - var tool = new Tool - { - Name = "CppCheck", - Version = version, - }; - - var fileInfoFactory = new FileInfoFactory(uri => MimeType.Cpp, dataToInsert); - Dictionary fileDictionary = fileInfoFactory.Create(results); - var run = new Run() { - Tool = tool + Tool = new Tool { Name = "CppCheck", Version = version } }; - output.Initialize(run); - - if (fileDictionary != null && fileDictionary.Count > 0) { output.WriteFiles(fileDictionary); } - - output.OpenResults(); - output.WriteResults(results); - output.CloseResults(); + PersistResults(output, results, run); } } } diff --git a/src/Sarif.Converters/FortifyConverter.cs b/src/Sarif.Converters/FortifyConverter.cs index 2f2da4a24..c062cd002 100644 --- a/src/Sarif.Converters/FortifyConverter.cs +++ b/src/Sarif.Converters/FortifyConverter.cs @@ -7,7 +7,6 @@ using System.IO; using System.Linq; using System.Xml; -using Microsoft.CodeAnalysis.Sarif.Writers; namespace Microsoft.CodeAnalysis.Sarif.Converters { @@ -85,14 +84,6 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm } } - var tool = new Tool - { - Name = "Fortify" - }; - - var fileInfoFactory = new FileInfoFactory(MimeType.DetermineFromFileExtension, dataToInsert); - Dictionary fileDictionary = fileInfoFactory.Create(results); - var run = new Run() { Id = new RunAutomationDetails @@ -102,16 +93,10 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm Text = runDescription } }, - Tool = tool + Tool = new Tool { Name = "Fortify" } }; - output.Initialize(run); - - if (fileDictionary != null && fileDictionary.Count > 0) { output.WriteFiles(fileDictionary); } - - output.OpenResults(); - output.WriteResults(results); - output.CloseResults(); + PersistResults(output, results, run); } /// Converts a Fortify result to a static analysis results interchange format result. diff --git a/src/Sarif.Converters/FortifyFprConverter.cs b/src/Sarif.Converters/FortifyFprConverter.cs index 165618e50..8de3da2fa 100644 --- a/src/Sarif.Converters/FortifyFprConverter.cs +++ b/src/Sarif.Converters/FortifyFprConverter.cs @@ -31,9 +31,8 @@ internal class FortifyFprConverter : ToolFileConverterBase private string _automationId; private string _originalUriBasePath; private List _results = new List(); - private List _toolNotifications; private Dictionary _fileDictionary; - private Dictionary _ruleDictionary; + private Dictionary _ruleDictionary; private Dictionary _tflToNodeIdDictionary; private Dictionary _tflToSnippetIdDictionary; private Dictionary _locationToSnippetIdDictionary; @@ -50,9 +49,8 @@ public FortifyFprConverter() _strings = new FortifyFprStrings(_nameTable); _results = new List(); - _toolNotifications = new List(); _fileDictionary = new Dictionary(); - _ruleDictionary = new Dictionary(); + _ruleDictionary = new Dictionary(); _tflToNodeIdDictionary = new Dictionary(); _tflToSnippetIdDictionary = new Dictionary(); _locationToSnippetIdDictionary = new Dictionary(); @@ -89,8 +87,8 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm }; _invocation = new Invocation(); + _invocation.ToolNotifications = new List(); _results.Clear(); - _toolNotifications.Clear(); _fileDictionary.Clear(); _ruleDictionary.Clear(); _tflToNodeIdDictionary.Clear(); @@ -116,7 +114,8 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm InstanceId = _automationId + "/" }, Tool = tool, - Invocations = new[] { _invocation } + Invocations = new[] { _invocation }, + Resources = new Resources { Rules = _ruleDictionary} }; if (!string.IsNullOrWhiteSpace(_originalUriBasePath)) @@ -128,28 +127,7 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm }; } - output.Initialize(run); - - (output as ResultLogJsonWriter).WriteInvocations(run.Invocations); - - if (_fileDictionary.Any()) - { - output.WriteFiles(_fileDictionary); - } - - output.OpenResults(); - output.WriteResults(_results); - output.CloseResults(); - - if (_ruleDictionary.Any()) - { - output.WriteRules(_ruleDictionary); - } - - if (_toolNotifications.Any()) - { - output.WriteToolNotifications(_toolNotifications); - } + PersistResults(output, _results, run); } private void ParseFprFile(Stream input) @@ -871,7 +849,7 @@ private void ParseErrors() string errorCode = _reader.GetAttribute(_strings.CodeAttribute); string message = _reader.ReadElementContentAsString(); - _toolNotifications.Add(new Notification + _invocation.ToolNotifications.Add(new Notification { Id = errorCode, Level = NotificationLevel.Error, @@ -930,7 +908,7 @@ private void AddMessagesToResults() { foreach (Result result in _results) { - IRule rule; + Rule rule; if (_ruleDictionary.TryGetValue(result.RuleId, out rule)) { Message message = rule.ShortDescription ?? rule.FullDescription; diff --git a/src/Sarif.Converters/FxCopConverter.cs b/src/Sarif.Converters/FxCopConverter.cs index 3e69068a9..68976c588 100644 --- a/src/Sarif.Converters/FxCopConverter.cs +++ b/src/Sarif.Converters/FxCopConverter.cs @@ -10,7 +10,6 @@ using System.Reflection; using System.Xml; using System.Xml.Schema; -using Microsoft.CodeAnalysis.Sarif.Writers; namespace Microsoft.CodeAnalysis.Sarif.Converters { @@ -53,46 +52,27 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm reader.ResultRead += (FxCopLogReader.Context current) => { results.Add(CreateResult(current)); }; reader.Read(context, input); - Tool tool = new Tool - { - Name = "FxCop" - }; - - var fileInfoFactory = new FileInfoFactory(MimeType.DetermineFromFileExtension, dataToInsert); - Dictionary fileDictionary = fileInfoFactory.Create(results); - var run = new Run() { - Tool = tool + Tool = new Tool { Name = "FxCop"} }; - output.Initialize(run); - - if (fileDictionary != null && fileDictionary.Any()) - { - output.WriteFiles(fileDictionary); - } - - if (LogicalLocations != null && LogicalLocations.Any()) - { - output.WriteLogicalLocations(LogicalLocations); - } - - output.OpenResults(); - output.WriteResults(results); - output.CloseResults(); - if (rules.Count > 0) { - IDictionary rulesDictionary = new Dictionary(); + IDictionary rulesDictionary = new Dictionary(); foreach (Rule rule in rules) { rulesDictionary[rule.Id] = rule; } - output.WriteRules(rulesDictionary); + run.Resources = new Resources + { + Rules = rulesDictionary + }; } + + PersistResults(output, results, run); } internal Rule CreateRule(FxCopLogReader.Context context) diff --git a/src/Sarif.Converters/PREFastConverter.cs b/src/Sarif.Converters/PREFastConverter.cs index 4314595fe..5dfce290b 100644 --- a/src/Sarif.Converters/PREFastConverter.cs +++ b/src/Sarif.Converters/PREFastConverter.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Xml.Serialization; using Microsoft.CodeAnalysis.Sarif.Converters.PREFastObjectModel; -using Microsoft.CodeAnalysis.Sarif.Writers; using System.Xml; namespace Microsoft.CodeAnalysis.Sarif.Converters @@ -26,19 +25,6 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm LogicalLocations.Clear(); - var tool = new Tool - { - Name = ToolFormat.PREfast, - FullName = "PREfast Code Analysis" - }; - - var run = new Run() - { - Tool = tool, - ColumnKind = ColumnKind.Utf16CodeUnits - }; - - output.Initialize(run); XmlReaderSettings settings = new XmlReaderSettings { @@ -57,22 +43,14 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm results.Add(CreateResult(entry)); } - var fileInfoFactory = new FileInfoFactory(MimeType.DetermineFromFileExtension, dataToInsert); - Dictionary fileDictionary = fileInfoFactory.Create(results); - - if (fileDictionary?.Any() == true) - { - output.WriteFiles(fileDictionary); - } - - if (LogicalLocations != null && LogicalLocations.Any()) + var run = new Run() { - output.WriteLogicalLocations(LogicalLocations); - } + Tool = new Tool { Name = "PREfast", FullName = "PREfast Code Analysis" }, + ColumnKind = ColumnKind.Utf16CodeUnits, + LogicalLocations = LogicalLocations + }; - output.OpenResults(); - output.WriteResults(results); - output.CloseResults(); + PersistResults(output, results, run); } } diff --git a/src/Sarif.Converters/PylintConverter.cs b/src/Sarif.Converters/PylintConverter.cs index 21a26d5cd..442665ad7 100644 --- a/src/Sarif.Converters/PylintConverter.cs +++ b/src/Sarif.Converters/PylintConverter.cs @@ -4,8 +4,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using Microsoft.CodeAnalysis.Sarif.Writers; using Microsoft.CodeAnalysis.Sarif.Converters.PylintObjectModel; namespace Microsoft.CodeAnalysis.Sarif.Converters @@ -26,18 +24,6 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm PylintLog log = logReader.ReadLog(input); - Tool tool = new Tool - { - Name = "Pylint" - }; - - var run = new Run() - { - Tool = tool - }; - - output.Initialize(run); - var results = new List(); foreach (PylintLogEntry entry in log) @@ -45,17 +31,7 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm results.Add(CreateResult(entry)); } - var fileInfoFactory = new FileInfoFactory(MimeType.DetermineFromFileExtension, dataToInsert); - Dictionary fileDictionary = fileInfoFactory.Create(results); - - if (fileDictionary?.Any() == true) - { - output.WriteFiles(fileDictionary); - } - - output.OpenResults(); - output.WriteResults(results); - output.CloseResults(); + PersistResults(output, results, "Pylint"); } internal Result CreateResult(PylintLogEntry defect) diff --git a/src/Sarif.Converters/SemmleQlConverter.cs b/src/Sarif.Converters/SemmleQlConverter.cs index ed60294a8..3af6e4569 100644 --- a/src/Sarif.Converters/SemmleQlConverter.cs +++ b/src/Sarif.Converters/SemmleQlConverter.cs @@ -7,8 +7,8 @@ using System.IO; using System.Linq; using System.Text; -using Microsoft.CodeAnalysis.Sarif.Writers; using CsvHelper; +using Microsoft.CodeAnalysis.Sarif.Visitors; namespace Microsoft.CodeAnalysis.Sarif.Converters { @@ -67,31 +67,7 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm var results = GetResultsFromStream(input); - var fileInfoFactory = new FileInfoFactory(MimeType.DetermineFromFileExtension, dataToInsert); - Dictionary fileDictionary = fileInfoFactory.Create(results); - - var tool = new Tool - { - Name = "Semmle QL" - }; - - var run = new Run() - { - Tool = tool - }; - - output.Initialize(run); - - output.WriteFiles(fileDictionary); - - output.OpenResults(); - output.WriteResults(results); - output.CloseResults(); - - if (_toolNotifications.Any()) - { - output.WriteToolNotifications(_toolNotifications); - } + PersistResults(output, results, "Semmle QL"); } private Result[] GetResultsFromStream(Stream input) diff --git a/src/Sarif.Converters/StaticDriverVerifierConverter.cs b/src/Sarif.Converters/StaticDriverVerifierConverter.cs index 191047b56..565db1ecb 100644 --- a/src/Sarif.Converters/StaticDriverVerifierConverter.cs +++ b/src/Sarif.Converters/StaticDriverVerifierConverter.cs @@ -45,26 +45,7 @@ public override void Convert(Stream input, IResultLogWriter output, OptionallyEm Result result = ProcessSdvDefectStream(input); var results = new Result[] { result }; - var tool = new Tool - { - Name = "StaticDriverVerifier", - }; - - var fileInfoFactory = new FileInfoFactory(null, dataToInsert); - Dictionary fileDictionary = fileInfoFactory.Create(results); - - var run = new Run() - { - Tool = tool - }; - - output.Initialize(run); - - if (fileDictionary != null && fileDictionary.Count > 0) { output.WriteFiles(fileDictionary); } - - output.OpenResults(); - output.WriteResults(results); - output.CloseResults(); + PersistResults(output, results, ToolFormat.StaticDriverVerifier); } private Result ProcessSdvDefectStream(Stream input) diff --git a/src/Sarif.Converters/TSLintConverter.cs b/src/Sarif.Converters/TSLintConverter.cs index 94d29bf50..6dd186813 100644 --- a/src/Sarif.Converters/TSLintConverter.cs +++ b/src/Sarif.Converters/TSLintConverter.cs @@ -6,7 +6,6 @@ using System.IO; using System.Linq; using Microsoft.CodeAnalysis.Sarif.Converters.TSLintObjectModel; -using Microsoft.CodeAnalysis.Sarif.Writers; namespace Microsoft.CodeAnalysis.Sarif.Converters { @@ -22,40 +21,17 @@ public TSLintConverter() public override void Convert(Stream input, IResultLogWriter output, OptionallyEmittedData dataToInsert) { input = input ?? throw new ArgumentNullException(nameof(input)); - output = output ?? throw new ArgumentNullException(nameof(output)); TSLintLog tsLintLog = logReader.ReadLog(input); - Tool tool = new Tool - { - Name = "TSLint" - }; - - var run = new Run() - { - Tool = tool - }; - - output.Initialize(run); - var results = new List(); - foreach(TSLintLogEntry entry in tsLintLog) + foreach (TSLintLogEntry entry in tsLintLog) { results.Add(CreateResult(entry)); } - var fileInfoFactory = new FileInfoFactory(MimeType.DetermineFromFileExtension, dataToInsert); - Dictionary fileDictionary = fileInfoFactory.Create(results); - - if (fileDictionary?.Any() == true) - { - output.WriteFiles(fileDictionary); - } - - output.OpenResults(); - output.WriteResults(results); - output.CloseResults(); + PersistResults(output, results, "TSLint"); } internal Result CreateResult(TSLintLogEntry entry) diff --git a/src/Sarif.Converters/ToolFileConverterBase.cs b/src/Sarif.Converters/ToolFileConverterBase.cs index 246777a55..44b0e5c88 100644 --- a/src/Sarif.Converters/ToolFileConverterBase.cs +++ b/src/Sarif.Converters/ToolFileConverterBase.cs @@ -1,11 +1,11 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; using System.IO; +using System.Linq; +using Microsoft.CodeAnalysis.Sarif.Visitors; +using Microsoft.CodeAnalysis.Sarif.Writers; namespace Microsoft.CodeAnalysis.Sarif.Converters { @@ -75,5 +75,54 @@ internal static string GetLogicalLocationName(string parentKey, string fullyQual return logicalName; } + + protected static Run PersistResults(IResultLogWriter output, IList results, string toolName) + { + var run = new Run() + { + Tool = new Tool { Name = toolName }, + ColumnKind = ColumnKind.Utf16CodeUnits + }; + + return PersistResults(output, results, run); + } + + protected static Run PersistResults(IResultLogWriter output, IList results, Run run) + { + output.Initialize(run); + + if (run.Invocations.Any()) + { + // TODO: add WriteInvocations to IResultLogWriter + // https://github.com/Microsoft/sarif-sdk/issues/1190 + (output as ResultLogJsonWriter).WriteInvocations(run.Invocations); + } + + run.Results = results; + var visitor = new AddFileReferencesVisitor(); + visitor.VisitRun(run); + + if (run.Files.Any()) + { + output.WriteFiles(run.Files); + } + + if (run.LogicalLocations.Any()) + { + output.WriteLogicalLocations(run.LogicalLocations); + } + + output.OpenResults(); + output.WriteResults(run.Results); + output.CloseResults(); + + // TODO: should we move these to be emitted at the beginning of the file? What order fo we prefer generaally + if (run.Resources?.Rules != null) + { + output.WriteRules(run.Resources?.Rules); + } + + return run; + } } } diff --git a/src/Sarif.Multitool/Program.cs b/src/Sarif.Multitool/Program.cs index fc31de495..41e489d7c 100644 --- a/src/Sarif.Multitool/Program.cs +++ b/src/Sarif.Multitool/Program.cs @@ -25,11 +25,11 @@ public static int Main(string[] args) (ValidateOptions validateOptions) => new ValidateCommand().Run(validateOptions), (ConvertOptions convertOptions) => ConvertCommand.Run(convertOptions), (RewriteOptions rewriteOptions) => new RewriteCommand().Run(rewriteOptions), - (TransformOptions transformOptions) => new TransformCommand().Run(transformOptions), + //(TransformOptions transformOptions) => new TransformCommand().Run(transformOptions), (MergeOptions mergeOptions) => new MergeCommand().Run(mergeOptions), (RebaseUriOptions rebaseOptions) => new RebaseUriCommand().Run(rebaseOptions), (AbsoluteUriOptions absoluteUriOptions) => new AbsoluteUriCommand().Run(absoluteUriOptions), - (ResultMatchingOptions baselineOptions) => new ResultMatchingCommand().Run(baselineOptions), + //(ResultMatchingOptions baselineOptions) => new ResultMatchingCommand().Run(baselineOptions), errs => 1); } } diff --git a/src/Sarif.Multitool/Rules/SarifValidationSkimmerBase.cs b/src/Sarif.Multitool/Rules/SarifValidationSkimmerBase.cs index dafb8fe88..d2355c601 100644 --- a/src/Sarif.Multitool/Rules/SarifValidationSkimmerBase.cs +++ b/src/Sarif.Multitool/Rules/SarifValidationSkimmerBase.cs @@ -87,7 +87,7 @@ protected virtual void Analyze(FileLocation fileLocation, string fileLocationPoi { } - protected virtual void Analyze(FileData fileData, string fileKey, string filePointer) + protected virtual void Analyze(FileData fileData, string filePointer) { } @@ -302,9 +302,9 @@ private void Visit(EdgeTraversal edgeTraversal, string edgeTraversalPointer) } } - private void Visit(FileData fileData, string fileKey, string filePointer) + private void Visit(FileData fileData, string filePointer) { - Analyze(fileData, fileKey, filePointer); + Analyze(fileData, filePointer); if (fileData.FileLocation != null) { @@ -697,12 +697,11 @@ private void Visit(Run run, string runPointer) if (run.Files != null) { - IDictionary files = run.Files; string filesPointer = runPointer.AtProperty(SarifPropertyName.Files); - foreach (string fileKey in files.Keys) + for (int i = 0; i < run.Files.Count; ++i) { - Visit(files[fileKey], fileKey, filesPointer.AtProperty(fileKey)); + Visit(run.Files[i], filesPointer.AtIndex(i)); } } diff --git a/src/Sarif.Multitool/Sarif.Multitool.csproj b/src/Sarif.Multitool/Sarif.Multitool.csproj index 5b49ddb82..d3937ba44 100644 --- a/src/Sarif.Multitool/Sarif.Multitool.csproj +++ b/src/Sarif.Multitool/Sarif.Multitool.csproj @@ -13,6 +13,11 @@ + + + + + diff --git a/src/Sarif.TestUtilities/ResultLogObjectWriter.cs b/src/Sarif.TestUtilities/ResultLogObjectWriter.cs index 5f29c4d47..9535d711e 100644 --- a/src/Sarif.TestUtilities/ResultLogObjectWriter.cs +++ b/src/Sarif.TestUtilities/ResultLogObjectWriter.cs @@ -24,11 +24,6 @@ public void Initialize(Run run) WriteTool(run.Tool); } - /// Writes a tool information entry to the log. - /// Thrown if the tool info block has already been - /// written. - /// The tool information to write. - /// public void WriteTool(Tool tool) { if (_tool != null) @@ -44,29 +39,10 @@ public void WriteInvocations(IEnumerable invocations) { } - /// - /// Write information about scanned files to the log. This information may appear - /// after the results, as the full list of scanned files might not be known until - /// all results have been generated. - /// - /// - /// A dictionary whose keys are the strings representing the locations of scanned files - /// and whose values provide information about those files. - /// - public void WriteFiles(IDictionary fileDictionary) + public void WriteFiles(IList fileDictionary) { throw new NotImplementedException(); } - - /// - /// Write information about the logical locations where results were produced to - /// the log. This information may appear after the results, as the full list of - /// logical locations will not be known until all results have been generated. - /// - /// - /// A dictionary whose keys are strings specifying a logical location and - /// whose values provide information about each component of the logical location. - /// public void WriteLogicalLocations(IList logicalLocations) { throw new NotImplementedException(); @@ -76,21 +52,6 @@ public void OpenResults() { } public void CloseResults() { } - /// - /// Writes a result to the log. - /// - /// - /// This function makes a copy of the data stored in ; if a - /// client wishes to reuse the result instance to avoid allocations they can do so. (This function - /// may invoke an internal copy of the result or serialize it in place to disk, etc.) - /// - /// - /// Thrown if the tool info is not yet written. - /// - /// - /// The result to write. - /// - /// public void WriteResult(Result result) { if (result == null) @@ -104,27 +65,6 @@ public void WriteResult(Result result) } } - /// - /// Writes a set of results to the log. - /// - /// - /// This function makes a copy of the data stored in ; if a - /// client wishes to reuse the result instance to avoid allocations they can do so. (This function - /// may invoke an internal copy of the result or serialize it in place to disk, etc.) - /// - /// - /// A file IO error occured. Clients implementing - /// should allow these exceptions to propagate. - /// - /// - /// Thrown if the tool info is not yet written. - /// - /// - /// Thrown if is null. - /// - /// - /// The results to write. - /// public void WriteResults(IEnumerable results) { foreach (Result result in results) @@ -133,7 +73,7 @@ public void WriteResults(IEnumerable results) } } - public void WriteRules(IDictionary rules) + public void WriteRules(IDictionary rules) { throw new NotImplementedException(); } diff --git a/src/Sarif.UnitTests/Core/RunTests.cs b/src/Sarif.UnitTests/Core/RunTests.cs index 67c3f9b78..b552f433c 100644 --- a/src/Sarif.UnitTests/Core/RunTests.cs +++ b/src/Sarif.UnitTests/Core/RunTests.cs @@ -5,6 +5,7 @@ using Xunit; using Newtonsoft.Json; using FluentAssertions; +using System.Collections.Generic; namespace Microsoft.CodeAnalysis.Sarif { @@ -43,5 +44,75 @@ private void RoundTripColumnKind(ColumnKind persistedValue, ColumnKind expectedR sarifLog = JsonConvert.DeserializeObject(json); sarifLog.Runs[0].ColumnKind.Should().Be(expectedRoundTrippedValue); } + + private const string s_UriBaseId = "$$SomeUriBaseId$$"; + private readonly Uri s_Uri = new Uri("relativeUri/toSomeFile.txt", UriKind.Relative); + + [Fact] + public void Run_RetrievesExistingFileDataObject() + { + Run run = BuildDefaultRunObject(); + + FileLocation fileLocation = BuildDefaultFileLocation(); + fileLocation.FileIndex.Should().Be(-1); + + // Retrieve existing file location. Our input file location should have its + // fileIndex property set as well. + RetrieveFileIndexAndValidate(run, fileLocation, expectedFileIndex: 1); + + // Repeat look-up with bad file index value. This should succeed and reset + // the fileIndex to the appropriate value. + fileLocation = BuildDefaultFileLocation(); + fileLocation.FileIndex = Int32.MaxValue; + RetrieveFileIndexAndValidate(run, fileLocation, expectedFileIndex: 1); + + // Now set a unique property bag on the file location. The property bag + // should not interfere with retrieving the file data object. The property bag should + // not be modified as a result of retrieving the file data index. + fileLocation = BuildDefaultFileLocation(); + fileLocation.FileIndex = Int32.MaxValue; + RetrieveFileIndexAndValidate(run, fileLocation, expectedFileIndex: 1); + } + + private void RetrieveFileIndexAndValidate(Run run, FileLocation fileLocation, int expectedFileIndex) + { + int fileIndex = run.GetFileIndex(fileLocation, addToFilesTableIfNotPresent: false); + fileLocation.FileIndex.Should().Be(fileIndex); + fileIndex.Should().Be(expectedFileIndex); + } + + private FileLocation BuildDefaultFileLocation() + { + return new FileLocation { Uri = s_Uri, UriBaseId = s_UriBaseId}; + } + + private Run BuildDefaultRunObject() + { + var run = new Run() + { + Files = new[] + { + new FileData + { + // This unused fileLocation exists simply to move testing + // to the second array element. Tests that depend on a fileIndex + // of '0' are suspect because 0 is a value that might be set as + // a default in some code paths, due to a bug + FileLocation = new FileLocation{ Uri = new Uri("unused")} + }, + new FileData + { + FileLocation = BuildDefaultFileLocation(), + Properties = new Dictionary + { + [Guid.NewGuid().ToString()] = null + } + } + } + }; + run.Files[0].FileLocation.FileIndex = 0; + + return run; + } } } diff --git a/src/Sarif/Core/Message.cs b/src/Sarif/Core/Message.cs index 120e4d9af..c8c1bdcb4 100644 --- a/src/Sarif/Core/Message.cs +++ b/src/Sarif/Core/Message.cs @@ -1,9 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; -using System.Linq; - namespace Microsoft.CodeAnalysis.Sarif { public partial class Message diff --git a/src/Sarif/Core/Result.cs b/src/Sarif/Core/Result.cs index cb8149905..0a09bd541 100644 --- a/src/Sarif/Core/Result.cs +++ b/src/Sarif/Core/Result.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; using System.Linq; namespace Microsoft.CodeAnalysis.Sarif diff --git a/src/Sarif/Core/Rule.cs b/src/Sarif/Core/Rule.cs index 745189d87..1ad844f99 100644 --- a/src/Sarif/Core/Rule.cs +++ b/src/Sarif/Core/Rule.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; using System.Collections.Generic; using System.Globalization; using System.Linq; diff --git a/src/Sarif/Core/Run.cs b/src/Sarif/Core/Run.cs index 6f15f07f3..eb02fd5d3 100644 --- a/src/Sarif/Core/Run.cs +++ b/src/Sarif/Core/Run.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; namespace Microsoft.CodeAnalysis.Sarif { @@ -16,13 +17,20 @@ public partial class Run private IDictionary _fileToIndexMap; - public int GetFileIndex(FileLocation fileLocation, bool addToFilesTableIfNotPresent = true) + public int GetFileIndex( + FileLocation fileLocation, + bool addToFilesTableIfNotPresent = true, + OptionallyEmittedData dataToInsert = OptionallyEmittedData.None, + Encoding encoding = null) { - if (fileLocation == null) throw new ArgumentNullException(nameof(fileLocation)); + if (fileLocation == null) { throw new ArgumentNullException(nameof(fileLocation)); } - if (this.Files == null || this.Files.Count == 0) + if (this.Files?.Count == 0) { - return -1; + if (!addToFilesTableIfNotPresent) + { + return -1; + } } if (_fileToIndexMap == null) @@ -42,34 +50,37 @@ public int GetFileIndex(FileLocation fileLocation, bool addToFilesTableIfNotPres // When we perform a files table look-up, only the uri and uriBaseId // are relevant; these properties together comprise the unique identity // of the file object. The file index, of course, does not relate to the - // file identity. We consciously exclude the properties as well. + // file identity. We consciously exclude the properties bag as well. + + // We will normalize the input fileLocation.Uri to make URIs more consistent + // throughout the emitted log. + fileLocation.Uri = new Uri(UriHelper.MakeValidUri(fileLocation.Uri.OriginalString)); var filesTableKey = new FileLocation { - Uri = new Uri(UriHelper.MakeValidUri(fileLocation.Uri.OriginalString)), + Uri = fileLocation.Uri, UriBaseId = fileLocation.UriBaseId }; - int fileIndex; - if (!_fileToIndexMap.TryGetValue(filesTableKey, out fileIndex)) + + if (!_fileToIndexMap.TryGetValue(filesTableKey, out int fileIndex)) { if (addToFilesTableIfNotPresent) { fileIndex = this.Files.Count; - // We did not find our item. We will set the index - fileLocation.FileIndex = fileIndex; - string mimeType = Writers.MimeType.DetermineFromFileExtension(filesTableKey.Uri.ToString()); - var fileData = FileData.Create(filesTableKey.Uri); + var fileData = FileData.Create( + filesTableKey.Uri, + dataToInsert, + mimeType: mimeType, + encoding); + fileData.FileLocation = fileLocation; - this.Files.Add(new FileData - { - MimeType = mimeType, - FileLocation = filesTableKey - }); + this.Files.Add(fileData); + _fileToIndexMap[filesTableKey] = fileIndex; } else @@ -80,6 +91,7 @@ public int GetFileIndex(FileLocation fileLocation, bool addToFilesTableIfNotPres } } + fileLocation.FileIndex = fileIndex; return fileIndex; } @@ -96,13 +108,11 @@ private void InitializeFileToIndexMap() var fileLocation = new FileLocation { Uri = fileData.FileLocation.Uri, - UriBaseId = fileData.FileLocation.UriBaseId + UriBaseId = fileData.FileLocation.UriBaseId, + FileIndex = i }; _fileToIndexMap[fileLocation] = i; - - // For good measure, we'll explicitly populate the file index property - this.Files[i].FileLocation.FileIndex = i; } } @@ -125,13 +135,13 @@ public bool ShouldSerializeColumnKind() return true; } - public bool ShouldSerializeFiles() { return this.Files != null && this.Files.Count > 0; } + public bool ShouldSerializeFiles() { return this.Files?.Count > 0; } public bool ShouldSerializeGraphs() { return this.Graphs != null && this.Graphs.Values.Any(); } public bool ShouldSerializeInvocations() { return this.Invocations != null && this.Invocations.Any((e) => e != null && !e.ValueEquals(EmptyInvocation)); } - public bool ShouldSerializeLogicalLocations() { return this.LogicalLocations != null && this.LogicalLocations.Count > 0; } + public bool ShouldSerializeLogicalLocations() { return this.LogicalLocations?.Count > 0; } public bool ShouldSerializeNewlineSequences() { return this.NewlineSequences != null && this.NewlineSequences.Any((s) => s != null); } } diff --git a/src/Sarif/Core/SerializedPropertyInfoEqualityComparer.cs b/src/Sarif/Core/SerializedPropertyInfoEqualityComparer.cs index 735866b91..e39b7b7ed 100644 --- a/src/Sarif/Core/SerializedPropertyInfoEqualityComparer.cs +++ b/src/Sarif/Core/SerializedPropertyInfoEqualityComparer.cs @@ -1,10 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; -using System.CodeDom.Compiler; using System.Collections.Generic; -using Microsoft.CodeAnalysis.Sarif.Readers; namespace Microsoft.CodeAnalysis.Sarif { diff --git a/src/Sarif/ExtensionMethods.cs b/src/Sarif/ExtensionMethods.cs index 4c26a70eb..28ea50f26 100644 --- a/src/Sarif/ExtensionMethods.cs +++ b/src/Sarif/ExtensionMethods.cs @@ -10,8 +10,6 @@ using System.Text.RegularExpressions; using System.Xml; -using Microsoft.CodeAnalysis.Sarif.Writers; - namespace Microsoft.CodeAnalysis.Sarif { public static class ExtensionMethods diff --git a/src/Sarif/IResultLogWriter.cs b/src/Sarif/IResultLogWriter.cs index 682dfba58..d808cf410 100644 --- a/src/Sarif/IResultLogWriter.cs +++ b/src/Sarif/IResultLogWriter.cs @@ -27,7 +27,7 @@ public interface IResultLogWriter /// A dictionary whose keys are the strings representing the locations of scanned files /// and whose values provide information about those files. /// - void WriteFiles(IDictionary fileDictionary); + void WriteFiles(IList fileDictionary); /// /// Write information about the logical locations where results were produced to @@ -50,7 +50,7 @@ public interface IResultLogWriter /// A dictionary whose keys are the URIs of scanned files and whose values provide /// information about those files. /// - void WriteRules(IDictionary rules); + void WriteRules(IDictionary rules); /// /// Initialize the results array associated with the current output log. SARIF producers that diff --git a/src/Sarif/NewLineIndex.cs b/src/Sarif/NewLineIndex.cs index df338e76b..b7424c15d 100644 --- a/src/Sarif/NewLineIndex.cs +++ b/src/Sarif/NewLineIndex.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Immutable; -using System.Collections.ObjectModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; diff --git a/src/Sarif/Properties/AssemblyInfo.cs b/src/Sarif/Properties/AssemblyInfo.cs index 2e78c599f..0f8f8033e 100644 --- a/src/Sarif/Properties/AssemblyInfo.cs +++ b/src/Sarif/Properties/AssemblyInfo.cs @@ -2,12 +2,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; -using Microsoft.CodeAnalysis.Sarif; - [assembly: InternalsVisibleTo("Sarif.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100433fbf156abe9718142bdbd48a440e779a1b708fd21486ee0ae536f4c548edf8a7185c1e3ac89ceef76c15b8cc2497906798779a59402f9b9e27281fb15e7111566cdc9a9f8326301d45320623c5222089cf4d0013f365ae729fb0a9c9d15138042825cd511a0f3d4887a7b92f4c2749f81b410813d297b73244cf64995effb1")] [assembly: InternalsVisibleTo("Sarif.Converters.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100433fbf156abe9718142bdbd48a440e779a1b708fd21486ee0ae536f4c548edf8a7185c1e3ac89ceef76c15b8cc2497906798779a59402f9b9e27281fb15e7111566cdc9a9f8326301d45320623c5222089cf4d0013f365ae729fb0a9c9d15138042825cd511a0f3d4887a7b92f4c2749f81b410813d297b73244cf64995effb1")] [assembly: InternalsVisibleTo("Sarif.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100433fbf156abe9718142bdbd48a440e779a1b708fd21486ee0ae536f4c548edf8a7185c1e3ac89ceef76c15b8cc2497906798779a59402f9b9e27281fb15e7111566cdc9a9f8326301d45320623c5222089cf4d0013f365ae729fb0a9c9d15138042825cd511a0f3d4887a7b92f4c2749f81b410813d297b73244cf64995effb1")] diff --git a/src/Sarif/Readers/LineMappingStreamReader.cs b/src/Sarif/Readers/LineMappingStreamReader.cs index 86d8bb824..230deb54e 100644 --- a/src/Sarif/Readers/LineMappingStreamReader.cs +++ b/src/Sarif/Readers/LineMappingStreamReader.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; using System.IO; -using Newtonsoft.Json; namespace Microsoft.CodeAnalysis.Sarif.Readers { diff --git a/src/Sarif/Readers/RuleDictionaryConverter.cs b/src/Sarif/Readers/RuleDictionaryConverter.cs index cb97b6cc9..fa32623c1 100644 --- a/src/Sarif/Readers/RuleDictionaryConverter.cs +++ b/src/Sarif/Readers/RuleDictionaryConverter.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; using System.Collections.Generic; -using System.Text; using Newtonsoft.Json; namespace Microsoft.CodeAnalysis.Sarif.Readers diff --git a/src/Sarif/Visitors/AbsoluteUrisVisitor.cs b/src/Sarif/Visitors/AbsoluteUrisVisitor.cs index 7f5b9ba7b..6a43aa691 100644 --- a/src/Sarif/Visitors/AbsoluteUrisVisitor.cs +++ b/src/Sarif/Visitors/AbsoluteUrisVisitor.cs @@ -90,7 +90,6 @@ private void FixFiles(Run run) newNode.FileLocation.UriBaseId = null; } - // fix dictionary newList[i] = newNode; } diff --git a/src/Sarif/Visitors/AddFileReferencesVisitor.cs b/src/Sarif/Visitors/AddFileReferencesVisitor.cs index d63d1ed63..f0cd92949 100644 --- a/src/Sarif/Visitors/AddFileReferencesVisitor.cs +++ b/src/Sarif/Visitors/AddFileReferencesVisitor.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information.using System; -using System; using System.Collections.Generic; namespace Microsoft.CodeAnalysis.Sarif.Visitors @@ -39,7 +38,6 @@ public override Run VisitRun(Run run) // Next, visit all run file locations. This will add any // previously unknown file objects to the files table. base.VisitRun(run); - return _currentRun; } @@ -47,11 +45,7 @@ public override FileLocation VisitFileLocation(FileLocation node) { node.FileIndex = _currentRun.GetFileIndex(node, addToFilesTableIfNotPresent: true); - return base.VisitFileLocation(node); - - - - + return base.VisitFileLocation(node); } } } diff --git a/src/Sarif/Visitors/LogicalLocationIndexRemapper.cs b/src/Sarif/Visitors/LogicalLocationIndexRemapper.cs index 867f63b63..a3a6e7608 100644 --- a/src/Sarif/Visitors/LogicalLocationIndexRemapper.cs +++ b/src/Sarif/Visitors/LogicalLocationIndexRemapper.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; using System.Collections.Generic; namespace Microsoft.CodeAnalysis.Sarif.Visitors diff --git a/src/Sarif/Visitors/RebaseUriVisitor.cs b/src/Sarif/Visitors/RebaseUriVisitor.cs index 002a653cb..665d660c7 100644 --- a/src/Sarif/Visitors/RebaseUriVisitor.cs +++ b/src/Sarif/Visitors/RebaseUriVisitor.cs @@ -4,8 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; -using Microsoft.CodeAnalysis.Sarif.Readers; using Newtonsoft.Json; namespace Microsoft.CodeAnalysis.Sarif.Visitors diff --git a/src/Sarif/Visitors/SarifTransformerUtilities.cs b/src/Sarif/Visitors/SarifTransformerUtilities.cs index 0d6177d6e..2e4e566d0 100644 --- a/src/Sarif/Visitors/SarifTransformerUtilities.cs +++ b/src/Sarif/Visitors/SarifTransformerUtilities.cs @@ -1,7 +1,6 @@ // Copyright(c) Microsoft.All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; using System.Collections.Generic; using System.Globalization; using Microsoft.CodeAnalysis.Sarif.Readers; diff --git a/src/Sarif/Visitors/UpdateIndicesVisitor.cs b/src/Sarif/Visitors/UpdateIndicesVisitor.cs index a4ec53d05..a26b70af3 100644 --- a/src/Sarif/Visitors/UpdateIndicesVisitor.cs +++ b/src/Sarif/Visitors/UpdateIndicesVisitor.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; using System.Collections.Generic; namespace Microsoft.CodeAnalysis.Sarif.Visitors diff --git a/src/Sarif/Visitors/VersionOneLogicalLocationKeyToLogicalLocationDataVisitor.cs b/src/Sarif/Visitors/VersionOneLogicalLocationKeyToLogicalLocationDataVisitor.cs index 296cd1810..ef465ef9e 100644 --- a/src/Sarif/Visitors/VersionOneLogicalLocationKeyToLogicalLocationDataVisitor.cs +++ b/src/Sarif/Visitors/VersionOneLogicalLocationKeyToLogicalLocationDataVisitor.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT // license. See LICENSE file in the project root for full license information. -using System; using System.Collections.Generic; using Microsoft.CodeAnalysis.Sarif.VersionOne; diff --git a/src/Sarif/Writers/ResultLogJsonWriter.cs b/src/Sarif/Writers/ResultLogJsonWriter.cs index 166ab5930..8aa7b80be 100644 --- a/src/Sarif/Writers/ResultLogJsonWriter.cs +++ b/src/Sarif/Writers/ResultLogJsonWriter.cs @@ -146,19 +146,19 @@ public void Initialize(Run run) } /// - /// Write information about scanned files to the log. This information may appear + /// A list containing information about the relevant files. This information may appear /// after the results, as the full list of scanned files might not be known until /// all results have been generated. /// - /// + /// /// A dictionary whose keys are the URIs of scanned files and whose values provide /// information about those files. /// - public void WriteFiles(IDictionary fileDictionary) + public void WriteFiles(IList files) { - if (fileDictionary == null) + if (files == null) { - throw new ArgumentNullException(nameof(fileDictionary)); + throw new ArgumentNullException(nameof(files)); } EnsureInitialized(); @@ -166,7 +166,7 @@ public void WriteFiles(IDictionary fileDictionary) EnsureStateNotAlreadySet(Conditions.Disposed | Conditions.FilesWritten); _jsonWriter.WritePropertyName("files"); - _serializer.Serialize(_jsonWriter, fileDictionary, typeof(Dictionary)); + _serializer.Serialize(_jsonWriter, files); _writeConditions |= Conditions.FilesWritten; } @@ -215,7 +215,7 @@ public void WriteInvocations(IEnumerable invocations) } - public void WriteRules(IDictionary rules) + public void WriteRules(IDictionary rules) { if (rules == null) { diff --git a/src/Sarif/Writers/SarifLogger.cs b/src/Sarif/Writers/SarifLogger.cs index 32f69ffe5..a9e8890d6 100644 --- a/src/Sarif/Writers/SarifLogger.cs +++ b/src/Sarif/Writers/SarifLogger.cs @@ -21,7 +21,7 @@ public class SarifLogger : IDisposable, IAnalysisLogger private JsonTextWriter _jsonTextWriter; private OptionallyEmittedData _dataToInsert; private ResultLogJsonWriter _issueLogJsonWriter; - private Dictionary _rules; + private Dictionary _rules; protected const LoggingOptions DefaultLoggingOptions = LoggingOptions.PrettyPrint; @@ -40,18 +40,25 @@ private static Run CreateRun( if (analysisTargets != null) { - run.GetFileIndex() run.Files = new List(); foreach (string target in analysisTargets) { - string fileDataKey = UriHelper.MakeValidUri(target); + Uri uri = new Uri(UriHelper.MakeValidUri(target)); var fileData = FileData.Create( new Uri(target, UriKind.RelativeOrAbsolute), dataToInsert); - run.Files[fileDataKey] = fileData; + var fileLocation = new FileLocation + { + Uri = uri + }; + + fileData.FileLocation = fileLocation; + + // This call will insert the file object into run.Files if not already present + fileData.FileLocation.FileIndex = run.GetFileIndex(fileData.FileLocation, addToFilesTableIfNotPresent: true); } } @@ -185,11 +192,11 @@ private SarifLogger(TextWriter textWriter, LoggingOptions loggingOptions) _issueLogJsonWriter = new ResultLogJsonWriter(_jsonTextWriter); } - public Dictionary Rules + public Dictionary Rules { get { - _rules = _rules ?? new Dictionary(); + _rules = _rules ?? new Dictionary(); return _rules; } } @@ -299,7 +306,9 @@ public void Log(IRule rule, Result result) return; } - Rules[result.RuleId] = rule; + // TODO: we need to finish eliminating the IRule interface from the OM + // https://github.com/Microsoft/sarif-sdk/issues/1189 + Rules[result.RuleId] = (Rule)rule; CaptureFilesInResult(result); _issueLogJsonWriter.WriteResult(result); @@ -309,7 +318,7 @@ private void CaptureFilesInResult(Result result) { if (result.AnalysisTarget != null) { - CaptureFile(result.AnalysisTarget.Uri); + CaptureFile(result.AnalysisTarget); } if (result.Locations != null) @@ -318,7 +327,7 @@ private void CaptureFilesInResult(Result result) { if (location.PhysicalLocation != null) { - CaptureFile(location.PhysicalLocation.FileLocation?.Uri); + CaptureFile(location.PhysicalLocation.FileLocation); } } } @@ -329,7 +338,7 @@ private void CaptureFilesInResult(Result result) { if (relatedLocation.PhysicalLocation != null) { - CaptureFile(relatedLocation.PhysicalLocation.FileLocation?.Uri); + CaptureFile(relatedLocation.PhysicalLocation.FileLocation); } } } @@ -340,7 +349,7 @@ private void CaptureFilesInResult(Result result) { foreach (StackFrame frame in stack.Frames) { - CaptureFile(frame.Location?.PhysicalLocation?.FileLocation?.Uri); + CaptureFile(frame.Location?.PhysicalLocation?.FileLocation); } } } @@ -364,7 +373,7 @@ private void CaptureFilesInResult(Result result) { foreach (FileChange fileChange in fix.FileChanges) { - CaptureFile(fileChange.FileLocation.Uri); + CaptureFile(fileChange.FileLocation); } } } @@ -379,40 +388,30 @@ private void CaptureThreadFlowLocations(IList locations) { if (tfl.Location?.PhysicalLocation != null) { - CaptureFile(tfl.Location.PhysicalLocation.FileLocation?.Uri); + CaptureFile(tfl.Location.PhysicalLocation.FileLocation); } } } - private void CaptureFile(Uri uri, string uriBaseId) - { - if (uri == null) { return; } - - _run.Files = _run.Files ?? new List(); - - FileLocation fileDataKey = new FileLocation - { - Uri = new Uri(UriHelper.MakeValidUri(uri.OriginalString)), - UriBaseId = uriBaseId - }; - - ; - - if (_run.Files.Contains(fileDataKey)) + private void CaptureFile(FileLocation fileLocation) + { + if (fileLocation == null || fileLocation.Uri == null) { - // Already populated return; } Encoding encoding = null; - try { encoding = Encoding.GetEncoding(_run.DefaultFileEncoding); } catch (ArgumentException) { } // Unrecognized or null encoding name - _run.Files[fileDataKey] = FileData.Create(uri, _dataToInsert, null, encoding); + _run.GetFileIndex( + fileLocation, + addToFilesTableIfNotPresent: true, + _dataToInsert, + encoding); } public void AnalyzingTarget(IAnalysisContext context) @@ -459,7 +458,9 @@ public void Log(ResultLevel messageKind, IAnalysisContext context, Region region if (context.Rule != null) { - Rules[context.Rule.Id] = context.Rule; + // TODO: finish removing IRule from the SDK + // https://github.com/Microsoft/sarif-sdk/issues/1189 + Rules[context.Rule.Id] = (Rule)context.Rule; } ruleMessageId = RuleUtilities.NormalizeRuleMessageId(ruleMessageId, context.Rule.Id); diff --git a/src/Sarif/Writers/SarifOneZeroZeroLogger.cs b/src/Sarif/Writers/SarifOneZeroZeroLogger.cs index 89f782b2c..7401c743a 100644 --- a/src/Sarif/Writers/SarifOneZeroZeroLogger.cs +++ b/src/Sarif/Writers/SarifOneZeroZeroLogger.cs @@ -2,10 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using Microsoft.CodeAnalysis.Sarif.Readers; -using Microsoft.CodeAnalysis.Sarif.VersionOne; -using Microsoft.CodeAnalysis.Sarif.Visitors; using Newtonsoft.Json; -using System; using System.Collections.Generic; using System.IO;