private SarifLog ConstructSarifLogFromMatchedResults(
            IEnumerable <MatchedResults> results,
            IEnumerable <Run> previousRuns,
            IEnumerable <Run> currentRuns)
        {
            if (currentRuns == null || !currentRuns.Any())
            {
                throw new ArgumentException(nameof(currentRuns));
            }

            // Results should all be from the same tool, so we'll pull the log from the first run.
            Tool tool = currentRuns.First().Tool.DeepClone();

            var run = new Run
            {
                Tool = tool,
                AutomationDetails = currentRuns.First().AutomationDetails,
            };

            IDictionary <string, SerializedPropertyInfo> properties = null;

            if (previousRuns != null && previousRuns.Count() != 0)
            {
                // We flow the baseline instance id forward (which becomes the
                // baseline guid for the merged log)
                run.BaselineGuid = previousRuns.First().AutomationDetails?.Guid;
            }

            bool initializeFromOldest = PropertyBagMergeBehavior.HasFlag(DictionaryMergeBehavior.InitializeFromOldest);

            if (initializeFromOldest)
            {
                // Find the 'oldest' log file and initialize properties from that log property bag
                properties = previousRuns.FirstOrDefault() != null
                    ? previousRuns.First().Properties
                    : currentRuns.First().Properties;
            }
            else
            {
                // Find the most recent log file instance and retain its property bag
                // Find the 'oldest' log file and initialize properties from that log property bag
                properties = currentRuns.Last().Properties;
            }

            var reportingDescriptors = new Dictionary <ReportingDescriptor, int>(ReportingDescriptor.ValueComparer);

            var indexRemappingVisitor = new RemapIndicesVisitor(currentFiles: null);

            properties = properties ?? new Dictionary <string, SerializedPropertyInfo>();

            List <Result> newRunResults = new List <Result>();

            foreach (MatchedResults resultPair in results)
            {
                Result result = resultPair.CalculateBasedlinedResult(PropertyBagMergeBehavior);

                IList <Artifact> files =
                    (PropertyBagMergeBehavior.HasFlag(DictionaryMergeBehavior.InitializeFromOldest) &&
                     (result.BaselineState == BaselineState.Unchanged || result.BaselineState == BaselineState.Updated))
                    ? resultPair.PreviousResult.OriginalRun.Artifacts
                    : resultPair.Run.Artifacts;

                indexRemappingVisitor.HistoricalFiles            = files;
                indexRemappingVisitor.HistoricalLogicalLocations = resultPair.Run.LogicalLocations;
                indexRemappingVisitor.VisitResult(result);

                if (result.RuleIndex != -1)
                {
                    ReportingDescriptor rule = resultPair.Run.Tool.Driver.Rules[0];
                    if (!reportingDescriptors.TryGetValue(rule, out int ruleIndex))
                    {
                        reportingDescriptors[rule] = run.Tool.Driver.Rules.Count;
                        run.Tool.Driver.Rules.Add(rule);
                    }
                    result.RuleIndex = ruleIndex;
                }

                newRunResults.Add(result);
            }

            run.Results   = newRunResults;
            run.Artifacts = indexRemappingVisitor.CurrentFiles;

            var graphs = new List <Graph>();
            //var ruleData = new Dictionary<string, ReportingDescriptor>();
            var invocations = new List <Invocation>();

            // TODO tool message strings are not currently handled
            // https://github.com/Microsoft/sarif-sdk/issues/1286

            foreach (Run currentRun in currentRuns)
            {
                if (currentRun.Graphs != null)
                {
                    graphs.AddRange(currentRun.Graphs);
                }

                if (currentRun.Invocations != null)
                {
                    invocations.AddRange(currentRun.Invocations);
                }

                if (PropertyBagMergeBehavior == DictionaryMergeBehavior.InitializeFromMostRecent)
                {
                    properties = currentRun.Properties;
                }
            }

            run.Graphs           = graphs;
            run.LogicalLocations = new List <LogicalLocation>(indexRemappingVisitor.RemappedLogicalLocationIndices.Keys);
            //run.Resources = new Resources() { MessageStrings = messageData, Rules = ruleData }; TODO
            run.Invocations = invocations;

            if (properties != null && properties.Count > 0)
            {
                run.Properties = properties;
            }

            return(new SarifLog()
            {
                Version = SarifVersion.Current,
                SchemaUri = new Uri(SarifUtilities.SarifSchemaUri),
                Runs = new Run[] { run }
            });
        }
Exemple #2
0
        private SarifLog ConstructSarifLogFromMatchedResults(
            IEnumerable <MatchedResults> results,
            IEnumerable <Run> previousRuns,
            IEnumerable <Run> currentRuns)
        {
            if (currentRuns == null || !currentRuns.Any())
            {
                throw new ArgumentException(nameof(currentRuns));
            }

            // Results should all be from the same tool, so we'll pull the log from the first run.
            Run  firstRun = currentRuns.First();
            Tool tool     = firstRun.Tool.DeepClone();

            // Only include the rules corresponding to matched results.
            tool.Driver.Rules = null;

            var run = new Run
            {
                Tool = tool
            };

            // If there was only one run, we can fill in more information because we don't need to
            // worry about it being different from run to run.
            if (currentRuns.Count() == 1)
            {
                run.AutomationDetails = firstRun.AutomationDetails;
                run.Conversion        = firstRun.Conversion;
                run.Taxonomies        = firstRun.Taxonomies;
                run.Translations      = firstRun.Translations;
                run.Policies          = firstRun.Policies;
                run.RedactionTokens   = firstRun.RedactionTokens;
                run.Language          = firstRun.Language;
            }

            IDictionary <string, SerializedPropertyInfo> properties = null;

            if (previousRuns != null && previousRuns.Count() != 0)
            {
                // We flow the baseline instance id forward (which becomes the
                // baseline guid for the merged log).
                run.BaselineGuid = previousRuns.First().AutomationDetails?.Guid;
            }

            bool initializeFromOldest = PropertyBagMergeBehavior.HasFlag(DictionaryMergeBehavior.InitializeFromOldest);

            if (initializeFromOldest)
            {
                // Find the 'oldest' log file and initialize properties from that log property bag.
                properties = previousRuns.FirstOrDefault() != null
                    ? previousRuns.First().Properties
                    : currentRuns.First().Properties;
            }
            else
            {
                // Find the most recent log file instance and retain its property bag.
                // Find the 'oldest' log file and initialize properties from that log property bag.
                properties = currentRuns.Last().Properties;
            }

            var reportingDescriptors = new Dictionary <string, int>();

            var indexRemappingVisitor = new RemapIndicesVisitor(currentArtifacts: null, currentLogicalLocations: null);

            properties ??= new Dictionary <string, SerializedPropertyInfo>();

            List <Result> newRunResults = new List <Result>();

            foreach (MatchedResults resultPair in results)
            {
                Result result = resultPair.CalculateBasedlinedResult(PropertyBagMergeBehavior);

                // TODO Shouldn't this just be HistoricalFiles = resultPair.Run.Artifacts?
                IList <Artifact> files =
                    (PropertyBagMergeBehavior.HasFlag(DictionaryMergeBehavior.InitializeFromOldest) &&
                     (result.BaselineState == BaselineState.Unchanged || result.BaselineState == BaselineState.Updated))
                    ? resultPair.PreviousResult.OriginalRun.Artifacts
                    : resultPair.Run.Artifacts;

                indexRemappingVisitor.HistoricalFiles            = files;
                indexRemappingVisitor.HistoricalLogicalLocations = resultPair.Run.LogicalLocations;
                indexRemappingVisitor.VisitResult(result);

                string ruleId = result.ResolvedRuleId(resultPair.Run);
                if (!string.IsNullOrEmpty(ruleId))
                {
                    if (reportingDescriptors.TryGetValue(ruleId, out int ruleIndex))
                    {
                        result.RuleIndex = ruleIndex;
                    }
                    else
                    {
                        ReportingDescriptor rule = result.GetRule(resultPair.Run);
                        int newIndex             = reportingDescriptors.Count;

                        reportingDescriptors[ruleId] = newIndex;

                        run.Tool.Driver.Rules ??= new List <ReportingDescriptor>();
                        run.Tool.Driver.Rules.Add(rule);

                        result.RuleIndex = newIndex;
                    }

                    result.RuleId = ruleId;
                }

                newRunResults.Add(result);
            }

            run.Results          = newRunResults;
            run.Artifacts        = indexRemappingVisitor.CurrentArtifacts;
            run.LogicalLocations = indexRemappingVisitor.CurrentLogicalLocations;

            var graphs      = new List <Graph>();
            var invocations = new List <Invocation>();

            // TODO tool message strings are not currently handled
            // https://github.com/Microsoft/sarif-sdk/issues/1286

            foreach (Run currentRun in currentRuns)
            {
                if (currentRun.Graphs != null)
                {
                    graphs.AddRange(currentRun.Graphs);
                }

                if (currentRun.Invocations != null)
                {
                    invocations.AddRange(currentRun.Invocations);
                }

                if (PropertyBagMergeBehavior == DictionaryMergeBehavior.InitializeFromMostRecent)
                {
                    properties = currentRun.Properties;
                }
            }

            run.Graphs      = graphs;
            run.Invocations = invocations;

            if (properties != null && properties.Count > 0)
            {
                run.Properties = properties;
            }

            return(new SarifLog()
            {
                Version = SarifVersion.Current,
                SchemaUri = new Uri(SarifUtilities.SarifSchemaUri),
                Runs = new Run[] { run }
            });
        }