From ea17e3c6336cff3bb2814043b304eeba7a56c620 Mon Sep 17 00:00:00 2001 From: Shaopeng <81775155+shaopeng-gh@users.noreply.github.com> Date: Wed, 7 Feb 2024 14:54:32 -0800 Subject: [PATCH] Enable using config file (#2775) --- src/Sarif.Driver/Sdk/AnalyzeOptionsBase.cs | 6 ++-- .../Sdk/MultithreadedAnalyzeCommandBase.cs | 2 +- src/Sarif/AnalyzeContextBase.cs | 14 +++++++- src/Sarif/IAnalysisContext.cs | 2 ++ .../PropertiesDictionaryExtensionMethods.cs | 35 +++++++++++++------ src/Sarif/RuleKindSet.cs | 25 +++++++++++++ .../TypedPropertiesDictionaryConverter.cs | 10 ++++++ 7 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 src/Sarif/RuleKindSet.cs diff --git a/src/Sarif.Driver/Sdk/AnalyzeOptionsBase.cs b/src/Sarif.Driver/Sdk/AnalyzeOptionsBase.cs index b9a678b4e..17cb4bce6 100644 --- a/src/Sarif.Driver/Sdk/AnalyzeOptionsBase.cs +++ b/src/Sarif.Driver/Sdk/AnalyzeOptionsBase.cs @@ -156,8 +156,8 @@ public IEnumerable RuleKindOption set => this.ruleKindOption = value?.Count() > 0 ? value : null; } - public HashSet RuleKinds => RuleKindOption != null ? - new HashSet(RuleKindOption) : - new HashSet(new[] { RuleKind.Sarif }); + public RuleKindSet RuleKinds => RuleKindOption != null ? + new RuleKindSet(RuleKindOption) : + new RuleKindSet(new List(new[] { RuleKind.Sarif })); } } diff --git a/src/Sarif.Driver/Sdk/MultithreadedAnalyzeCommandBase.cs b/src/Sarif.Driver/Sdk/MultithreadedAnalyzeCommandBase.cs index b13d60636..7e3ab3a95 100644 --- a/src/Sarif.Driver/Sdk/MultithreadedAnalyzeCommandBase.cs +++ b/src/Sarif.Driver/Sdk/MultithreadedAnalyzeCommandBase.cs @@ -319,7 +319,7 @@ public virtual TContext InitializeGlobalContextFromOptions(TOptions options, ref context.TargetFileSpecifiers = options.TargetFileSpecifiers?.Any() == true ? InitializeStringSet(options.TargetFileSpecifiers) : context.TargetFileSpecifiers; context.InvocationPropertiesToLog = options.InvocationPropertiesToLog?.Any() == true ? InitializeStringSet(options.InvocationPropertiesToLog) : context.InvocationPropertiesToLog; context.Traces = options.Trace.Any() ? InitializeStringSet(options.Trace) : context.Traces; - context.RuleKinds = options.RuleKinds; + context.RuleKinds = options.RuleKindOption != null ? options.RuleKinds : context.RuleKinds; } // Less-obviously throw-safe. We don't do these in the finally block because we'd prefer not to mask an earlier Exception during logger initialization. diff --git a/src/Sarif/AnalyzeContextBase.cs b/src/Sarif/AnalyzeContextBase.cs index 6646bac59..02b89e094 100644 --- a/src/Sarif/AnalyzeContextBase.cs +++ b/src/Sarif/AnalyzeContextBase.cs @@ -43,6 +43,7 @@ public virtual IEnumerable GetOptions() PostUriProperty, RecurseProperty, ResultKindsProperty, + RuleKindsProperty, RichReturnCodeProperty, TargetFileSpecifiersProperty, ThreadsProperty, @@ -68,7 +69,6 @@ public virtual IEnumerable GetOptions() public virtual IList RuntimeExceptions { get; set; } public virtual bool IsValidAnalysisTarget { get; set; } public virtual ReportingDescriptor Rule { get; set; } - public HashSet RuleKinds { get; set; } = new HashSet(); public PropertiesDictionary Policy { get; set; } public virtual IAnalysisLogger Logger { get; set; } public virtual RuntimeConditions RuntimeErrors { get; set; } @@ -202,6 +202,12 @@ public ResultKindSet ResultKinds set => this.Policy.SetProperty(ResultKindsProperty, value); } + public RuleKindSet RuleKinds + { + get => this.Policy.GetProperty(RuleKindsProperty); + set => this.Policy.SetProperty(RuleKindsProperty, value); + } + public virtual bool RichReturnCode { get => this.Policy.GetProperty(RichReturnCodeProperty); @@ -352,6 +358,12 @@ public virtual void Dispose() "One or more result kinds to persist to loggers. Valid values include None, NotApplicable, Pass, Fail, " + "Review, Open, Informational. Defaults to 'Fail'."); + public static PerLanguageOption RuleKindsProperty { get; } = + new PerLanguageOption( + "CoreSettings", nameof(RuleKinds), defaultValue: () => new RuleKindSet(new[] { RuleKind.Sarif }), + "One or more rule kinds that should be run. Valid values include Sarif, Ado, Ghas. " + + "Defaults to 'Sarif'."); + public static PerLanguageOption OutputFileOptionsProperty { get; } = new PerLanguageOption( "CoreSettings", nameof(OutputFileOptions), defaultValue: () => FilePersistenceOptions.PrettyPrint, diff --git a/src/Sarif/IAnalysisContext.cs b/src/Sarif/IAnalysisContext.cs index 7bbc318b4..eef967fb8 100644 --- a/src/Sarif/IAnalysisContext.cs +++ b/src/Sarif/IAnalysisContext.cs @@ -49,6 +49,8 @@ public interface IAnalysisContext : IDisposable ResultKindSet ResultKinds { get; set; } + RuleKindSet RuleKinds { get; set; } + public ISet InsertProperties { get; set; } OptionallyEmittedData DataToInsert { get; set; } diff --git a/src/Sarif/PropertiesDictionaryExtensionMethods.cs b/src/Sarif/PropertiesDictionaryExtensionMethods.cs index 123ea19d3..6f7f8944a 100644 --- a/src/Sarif/PropertiesDictionaryExtensionMethods.cs +++ b/src/Sarif/PropertiesDictionaryExtensionMethods.cs @@ -80,35 +80,42 @@ public static class PropertiesDictionaryExtensionMethods } } - StringSet stringSet = property as StringSet; + var stringSet = property as StringSet; if (stringSet != null) { SaveSet(writer, stringSet, key); continue; } - IntegerSet integerSet = property as IntegerSet; + var integerSet = property as IntegerSet; if (integerSet != null) { SaveSet(writer, integerSet, key); continue; } - FailureLevelSet failureLevelSet = property as FailureLevelSet; + var failureLevelSet = property as FailureLevelSet; if (failureLevelSet != null) { SaveSet(writer, failureLevelSet, key); continue; } - ResultKindSet resultKindSet = property as ResultKindSet; + var resultKindSet = property as ResultKindSet; if (resultKindSet != null) { SaveSet(writer, resultKindSet, key); continue; } - IDictionary pb = property as IDictionary; + var ruleKindSet = property as RuleKindSet; + if (ruleKindSet != null) + { + SaveSet(writer, ruleKindSet, key); + continue; + } + + var pb = property as IDictionary; if (pb != null) { pb.SavePropertiesToXmlStream(writer, settings, key, settingNameToDescriptionMap); @@ -158,7 +165,7 @@ private static void SaveSet(XmlWriter writer, HashSet items, string key) writer.WriteAttributeString(KEY_ID, key); writer.WriteAttributeString(TYPE_ID, items.GetType().Name); - T[] sorted = new T[items.Count]; + var sorted = new T[items.Count]; items.CopyTo(sorted, 0); Array.Sort(sorted); @@ -233,29 +240,36 @@ public static void LoadPropertiesFromXmlStream(this IDictionary propertyBag, Xml if (typeName == STRING_SET_ID || typeName == INTEGER_SET_ID || typeName == RESULT_KIND_SET_ID || + typeName == RULE_KIND_SET_ID || typeName == FAILURE_LEVEL_SET_ID) { if (typeName == STRING_SET_ID) { - StringSet set = new StringSet(); + var set = new StringSet(); propertyBag[key] = set; LoadSet(set, reader); } else if (typeName == INTEGER_SET_ID) { - IntegerSet set = new IntegerSet(); + var set = new IntegerSet(); propertyBag[key] = set; LoadSet(set, reader); } else if (typeName == FAILURE_LEVEL_SET_ID) { - FailureLevelSet set = new FailureLevelSet(); + var set = new FailureLevelSet(); + propertyBag[key] = set; + LoadSet(set, reader); + } + else if (typeName == RESULT_KIND_SET_ID) + { + var set = new ResultKindSet(); propertyBag[key] = set; LoadSet(set, reader); } else { - ResultKindSet set = new ResultKindSet(); + var set = new RuleKindSet(); propertyBag[key] = set; LoadSet(set, reader); } @@ -359,6 +373,7 @@ private static Type GetType(string typeName) private const string PROPERTY_ID = "Property"; private const string STRING_SET_ID = "StringSet"; private const string INTEGER_SET_ID = "IntegerSet"; + private const string RULE_KIND_SET_ID = "RuleKindSet"; private const string RESULT_KIND_SET_ID = "ResultKindSet"; private const string FAILURE_LEVEL_SET_ID = "FailureLevelSet"; internal const string PROPERTIES_ID = "Properties"; diff --git a/src/Sarif/RuleKindSet.cs b/src/Sarif/RuleKindSet.cs new file mode 100644 index 000000000..9a6403be4 --- /dev/null +++ b/src/Sarif/RuleKindSet.cs @@ -0,0 +1,25 @@ +// 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.Runtime.Serialization; + +using Newtonsoft.Json; + +namespace Microsoft.CodeAnalysis.Sarif +{ + [Serializable] + [JsonConverter(typeof(TypedPropertiesDictionaryConverter))] + public class RuleKindSet : HashSet + { + public RuleKindSet() { } + + public RuleKindSet(IEnumerable values) : base(values) { } + + protected RuleKindSet(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/src/Sarif/TypedPropertiesDictionaryConverter.cs b/src/Sarif/TypedPropertiesDictionaryConverter.cs index dd9bcb6e8..168780020 100644 --- a/src/Sarif/TypedPropertiesDictionaryConverter.cs +++ b/src/Sarif/TypedPropertiesDictionaryConverter.cs @@ -53,6 +53,11 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist ja = JArray.Load(reader); return new IntegerSet(ja.Values().Select(token => int.Parse(token.ToString()))); } + else if (objectType == typeof(RuleKindSet)) + { + ja = JArray.Load(reader); + return new IntegerSet(ja.Values().Select(token => int.Parse(token.ToString()))); + } else if (objectType == typeof(Version)) { return JsonConvert.DeserializeObject(reader.ReadAsString(), _versionConverter); @@ -131,6 +136,11 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s ja = new JArray(resultKindSet.Select(i => new JValue(i))); ja.WriteTo(writer); } + else if (value is RuleKindSet ruleKindSet) + { + ja = new JArray(ruleKindSet.Select(i => new JValue(i))); + ja.WriteTo(writer); + } else { var dictionary = (IDictionary)value;