public IAnalysisIssue Convert(Message cFamilyIssue, string sqLanguage, ICFamilyRulesConfig rulesConfiguration) { // Lines and character positions are 1-based Debug.Assert(cFamilyIssue.Line > 0); // BUT special case of EndLine=0, Column=0, EndColumn=0 meaning "select the whole line" Debug.Assert(cFamilyIssue.EndLine >= 0); Debug.Assert(cFamilyIssue.Column > 0 || cFamilyIssue.Column == 0); Debug.Assert(cFamilyIssue.EndColumn > 0 || cFamilyIssue.EndLine == 0); // Look up default severity and type var defaultSeverity = rulesConfiguration.RulesMetadata[cFamilyIssue.RuleKey].DefaultSeverity; var defaultType = rulesConfiguration.RulesMetadata[cFamilyIssue.RuleKey].Type; var fileContents = LoadFileContentsOfReportedFiles(cFamilyIssue); var locations = cFamilyIssue.Parts .Select(x => ToAnalysisIssueLocation(x, fileContents)) .ToArray(); // If PartsMakeFlow is set to true the issues are expected to be in the reversed order if (locations != null && cFamilyIssue.PartsMakeFlow) { Array.Reverse(locations); } var flows = locations.Any() ? new[] { new AnalysisIssueFlow(locations) } : null; return(ToAnalysisIssue(cFamilyIssue, sqLanguage, defaultSeverity, defaultType, flows, fileContents)); }
public ICFamilyRulesConfig GetEffectiveRulesConfig(string languageKey, ICFamilyRulesConfig defaultRulesConfig, UserSettings userSettings) { if (defaultRulesConfig == null) { throw new ArgumentNullException(nameof(defaultRulesConfig)); } // Optimisation - if there are no user-specified rules settings then just return the default if ((userSettings?.Rules?.Count ?? 0) == 0) { logger.WriteLine(CoreStrings.EffectiveRules_NoUserSettings); return(defaultRulesConfig); } var effectiveConfig = configCache.FindConfig(languageKey, defaultRulesConfig, userSettings); if (effectiveConfig != null) { logger.WriteLine(CoreStrings.EffectiveRules_CacheHit); } else { logger.WriteLine(CoreStrings.EffectiveRules_CacheMiss); effectiveConfig = new DynamicCFamilyRulesConfig(defaultRulesConfig, userSettings); configCache.Add(languageKey, defaultRulesConfig, userSettings, effectiveConfig); } return(effectiveConfig); }
public ICFamilyRulesConfig GetEffectiveRulesConfig(string languageKey, ICFamilyRulesConfig defaultRulesConfig, RulesSettings customSettings) { if (languageKey == null) { throw new ArgumentNullException(nameof(languageKey)); } if (defaultRulesConfig == null) { throw new ArgumentNullException(nameof(defaultRulesConfig)); } if (customSettings == null) { throw new ArgumentNullException(nameof(customSettings)); } var effectiveConfig = configCache.FindConfig(languageKey, defaultRulesConfig, customSettings); if (effectiveConfig != null) { logger.WriteLine(CoreStrings.EffectiveRules_CacheHit); return(effectiveConfig); } logger.WriteLine(CoreStrings.EffectiveRules_CacheMiss); effectiveConfig = new DynamicCFamilyRulesConfig(defaultRulesConfig, customSettings, logger); configCache.Add(languageKey, defaultRulesConfig, customSettings, effectiveConfig); return(effectiveConfig); }
internal /* for testing */ static string[] GetKeyValueOptionsList(ICFamilyRulesConfig rulesConfiguration) { var options = GetDefaultOptions(rulesConfiguration); options.Add("internal.qualityProfile", string.Join(",", rulesConfiguration.ActivePartialRuleKeys)); var data = options.Select(kv => kv.Key + "=" + kv.Value).ToArray(); return(data); }
internal /* for testing */ static bool IsIssueForActiveRule(Message message, ICFamilyRulesConfig rulesConfiguration) { // Currently (v6.3) the subprocess.exe will always run the native CLang rules, so those issues // could be returned even if they were not activated in the profile. // In addition, in v6.4+ there are internal rules that are always enabled and will always return // issues. Filtering for active rules will also remove those internal issues since the corresponding // rules will never be active in a quality profile. return(rulesConfiguration.ActivePartialRuleKeys.Contains(message.RuleKey, CFamilyShared.RuleKeyComparer)); }
private static IEnumerable <string> CalculateActiveRules(ICFamilyRulesConfig defaultRulesConfig, RulesSettings customRulesSettings) { // We're only interested settings for rules that are for the same language as the supplied rules configuration. // The rule keys in the custom rules settings include the repo prefix, but the rule keys in the default rules config do not. var partialKeyToConfigMap = GetFilteredRulesKeyedByPartialKey(customRulesSettings, defaultRulesConfig.LanguageKey); var deactivatedByUser = partialKeyToConfigMap.Where(kvp => kvp.Value.Level == RuleLevel.Off).Select(kvp => kvp.Key); var activatedByUser = partialKeyToConfigMap.Where(kvp => kvp.Value.Level == RuleLevel.On).Select(kvp => kvp.Key); return(defaultRulesConfig.ActivePartialRuleKeys .Concat(activatedByUser) .Except(deactivatedByUser, CFamilyShared.RuleKeyComparer) .Distinct(CFamilyShared.RuleKeyComparer).ToArray()); }
public ICFamilyRulesConfig FindConfig(string languageKey, ICFamilyRulesConfig sourceConfig, UserSettings sourceSettings) { if (!languageToConfigMap.TryGetValue(languageKey, out var cachedValue)) { return(null); } if (object.ReferenceEquals(sourceConfig, cachedValue.SourceConfig) && object.ReferenceEquals(sourceSettings, cachedValue.SourceSettings)) { return(cachedValue.EffectiveConfig); } languageToConfigMap.Remove(languageKey); // entry doesn't match -> remove it return(null); }
private static Dictionary <string, string> GetDefaultOptions(ICFamilyRulesConfig rulesConfiguration) { Dictionary <string, string> defaults = new Dictionary <string, string>(); foreach (string ruleKey in rulesConfiguration.AllPartialRuleKeys) { if (rulesConfiguration.RulesParameters.TryGetValue(ruleKey, out IDictionary <string, string> ruleParams)) { foreach (var param in ruleParams) { string optionKey = ruleKey + "." + param.Key; defaults.Add(optionKey, param.Value); } } } return(defaults); }
public DynamicCFamilyRulesConfig(ICFamilyRulesConfig defaultRulesConfig, UserSettings userSettings) { this.defaultRulesConfig = defaultRulesConfig ?? throw new ArgumentNullException(nameof(defaultRulesConfig)); if ((userSettings?.Rules?.Count ?? 0) == 0) { ActivePartialRuleKeys = defaultRulesConfig.ActivePartialRuleKeys; RulesMetadata = defaultRulesConfig.RulesMetadata; RulesParameters = defaultRulesConfig.RulesParameters; } else { ActivePartialRuleKeys = CalculateActiveRules(defaultRulesConfig, userSettings); RulesMetadata = new Dictionary <string, RuleMetadata>(); RulesParameters = new Dictionary <string, IDictionary <string, string> >(); CalculateEffectiveSettings(defaultRulesConfig, userSettings); } }
internal /* for testing */ DynamicCFamilyRulesConfig(ICFamilyRulesConfig defaultRulesConfig, RulesSettings customRulesSettings, ILogger logger, IEnumerable <string> excludedRuleKeys) { this.defaultRulesConfig = defaultRulesConfig ?? throw new ArgumentNullException(nameof(defaultRulesConfig)); if (customRulesSettings == null) { throw new ArgumentNullException(nameof(customRulesSettings)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (customRulesSettings.Rules.Count == 0) { logger.WriteLine(CoreStrings.CFamily_NoCustomRulesSettings); } var modifiedCustomRules = DisableExcludedRules(customRulesSettings, excludedRuleKeys, logger); ActivePartialRuleKeys = CalculateActiveRules(defaultRulesConfig, modifiedCustomRules); RulesMetadata = new Dictionary <string, RuleMetadata>(); RulesParameters = new Dictionary <string, IDictionary <string, string> >(); CalculateEffectiveSettings(defaultRulesConfig, modifiedCustomRules); }
private void CalculateEffectiveSettings(ICFamilyRulesConfig defaultRulesConfig, RulesSettings customRulesSettings) { Debug.Assert(customRulesSettings?.Rules != null && customRulesSettings.Rules.Count != 0); foreach (var partialRuleKey in defaultRulesConfig.AllPartialRuleKeys) { // Not all rules have params, but all should have metadata Debug.Assert(defaultRulesConfig.RulesMetadata[partialRuleKey] != null); var defaultMetadata = defaultRulesConfig.RulesMetadata[partialRuleKey]; defaultRulesConfig.RulesParameters.TryGetValue(partialRuleKey, out var defaultParams); var fullRuleKey = GetFullRuleKey(defaultRulesConfig.LanguageKey, partialRuleKey); customRulesSettings.Rules.TryGetValue(fullRuleKey, out var userRuleConfig); RulesMetadata[partialRuleKey] = GetEffectiveMetadata(defaultMetadata, userRuleConfig); var effectiveParams = GetEffectiveParameters(defaultParams, userRuleConfig?.Parameters); if (effectiveParams != null) { RulesParameters[partialRuleKey] = effectiveParams; } } }
protected virtual /* for testing */ ICFamilyRulesConfig CreateConfiguration(string languageKey, ICFamilyRulesConfig sonarWayConfig, RulesSettings settings) => effectiveConfigCalculator.GetEffectiveRulesConfig(languageKey, sonarWayConfig, settings);
public void Add(string languageKey, ICFamilyRulesConfig sourceConfig, UserSettings sourceSettings, ICFamilyRulesConfig effectiveConfig) { languageToConfigMap[languageKey] = new CacheEntry(sourceConfig, sourceSettings, effectiveConfig); }
public CacheEntry(ICFamilyRulesConfig sourceConfig, UserSettings sourceSettings, ICFamilyRulesConfig effectiveConfig) { SourceConfig = sourceConfig; SourceSettings = sourceSettings; EffectiveConfig = effectiveConfig; }
public DynamicCFamilyRulesConfig(ICFamilyRulesConfig defaultRulesConfig, RulesSettings customRulesSettings, ILogger logger) : this(defaultRulesConfig, customRulesSettings, logger, ExcludedRulesKeys) { }
internal /* for testing */ static Sonarlint.Issue ToSonarLintIssue(Message cfamilyIssue, string sqLanguage, ICFamilyRulesConfig rulesConfiguration) { // Lines and character positions are 1-based Debug.Assert(cfamilyIssue.Line > 0); // BUT special case of EndLine=0, Column=0, EndColumn=0 meaning "select the whole line" Debug.Assert(cfamilyIssue.EndLine >= 0); Debug.Assert(cfamilyIssue.Column > 0 || cfamilyIssue.Column == 0); Debug.Assert(cfamilyIssue.EndColumn > 0 || cfamilyIssue.EndLine == 0); // Look up default severity and type var defaultSeverity = rulesConfiguration.RulesMetadata[cfamilyIssue.RuleKey].DefaultSeverity; var defaultType = rulesConfiguration.RulesMetadata[cfamilyIssue.RuleKey].Type; return(new Sonarlint.Issue() { FilePath = cfamilyIssue.Filename, Message = cfamilyIssue.Text, RuleKey = sqLanguage + ":" + cfamilyIssue.RuleKey, Severity = Convert(defaultSeverity), Type = Convert(defaultType), StartLine = cfamilyIssue.Line, EndLine = cfamilyIssue.EndLine, // We don't care about the columns in the special case EndLine=0 StartLineOffset = cfamilyIssue.EndLine == 0 ? 0 : cfamilyIssue.Column - 1, EndLineOffset = cfamilyIssue.EndLine == 0 ? 0 : cfamilyIssue.EndColumn - 1 }); }