diff --git a/src/Tools/GenerateAnalyzerNuspec/Program.cs b/src/Tools/GenerateAnalyzerNuspec/Program.cs index 2e9395713c..c2d3235d53 100644 --- a/src/Tools/GenerateAnalyzerNuspec/Program.cs +++ b/src/Tools/GenerateAnalyzerNuspec/Program.cs @@ -235,15 +235,15 @@ if (globalAnalyzerConfigsDir.Length > 0 && Directory.Exists(globalAnalyzerConfigsDir)) { - foreach (string editorconfig in Directory.EnumerateFiles(globalAnalyzerConfigsDir)) + foreach (string globalconfig in Directory.EnumerateFiles(globalAnalyzerConfigsDir)) { - if (Path.GetExtension(editorconfig) == ".editorconfig") + if (Path.GetExtension(globalconfig) == ".globalconfig") { - result.AppendLine(FileElement(Path.Combine(globalAnalyzerConfigsDir, editorconfig), $"build\\config")); + result.AppendLine(FileElement(Path.Combine(globalAnalyzerConfigsDir, globalconfig), $"buildtransitive\\config")); } else { - throw new InvalidDataException($"Encountered a file with unexpected extension: {editorconfig}"); + throw new InvalidDataException($"Encountered a file with unexpected extension: {globalconfig}"); } } } diff --git a/src/Tools/GenerateDocumentationAndConfigFiles/Program.cs b/src/Tools/GenerateDocumentationAndConfigFiles/Program.cs index fdd02e4723..5aa7c734b2 100644 --- a/src/Tools/GenerateDocumentationAndConfigFiles/Program.cs +++ b/src/Tools/GenerateDocumentationAndConfigFiles/Program.cs @@ -252,7 +252,7 @@ void createPropsFiles() var fileContents = $@" - {disableNetAnalyzersImport}{getCodeAnalysisTreatWarningsAsErrors()}{getCompilerVisibleProperties()} + {disableNetAnalyzersImport}{getCompilerVisibleProperties()} "; var directory = Directory.CreateDirectory(propsFileDir); var fileWithPath = Path.Combine(directory.FullName, propsFileName); @@ -310,20 +310,6 @@ We rely on the additional props file '{propsFileToDisableNetAnalyzersInNuGetPack } } - string getCodeAnalysisTreatWarningsAsErrors() - { - var allRuleIds = string.Join(';', allRulesById.Keys); - return $@" - - - {allRuleIds} - $(WarningsNotAsErrors);$(CodeAnalysisRuleIds) - $(WarningsAsErrors);$(CodeAnalysisRuleIds) - "; - } - string getCompilerVisibleProperties() { return analyzerPackageName switch @@ -794,12 +780,15 @@ void CreateGlobalConfigsForVersion( { var analysisLevelVersionString = GetNormalizedVersionStringForEditorconfigFileNameSuffix(version); - foreach (var analysisMode in Enum.GetValues(typeof(AnalysisMode))) + foreach (var warnAsError in new[] { true, false }) { - CreateGlobalConfig(version, isShippedVersion, analysisLevelVersionString, (AnalysisMode)analysisMode!, releaseTrackingData, category: null); - foreach (var category in categories!) + foreach (var analysisMode in Enum.GetValues(typeof(AnalysisMode))) { - CreateGlobalConfig(version, isShippedVersion, analysisLevelVersionString, (AnalysisMode)analysisMode!, releaseTrackingData, category); + CreateGlobalConfig(version, isShippedVersion, analysisLevelVersionString, (AnalysisMode)analysisMode!, warnAsError, releaseTrackingData, category: null); + foreach (var category in categories!) + { + CreateGlobalConfig(version, isShippedVersion, analysisLevelVersionString, (AnalysisMode)analysisMode!, warnAsError, releaseTrackingData, category); + } } } } @@ -809,12 +798,14 @@ void CreateGlobalConfig( bool isShippedVersion, string analysisLevelVersionString, AnalysisMode analysisMode, + bool warnAsError, ImmutableArray releaseTrackingData, string? category) { var analysisLevelPropName = "AnalysisLevel"; var title = $"Rules from '{version}' release with '{analysisMode}' analysis mode"; var description = $"Rules with enabled-by-default state from '{version}' release with '{analysisMode}' analysis mode. Rules that are first released in a version later than '{version}' are disabled."; + if (category != null) { analysisLevelPropName += category; @@ -822,13 +813,23 @@ void CreateGlobalConfig( description = $"'{category}' {description}"; } - CreateGlobalconfig( - analyzerGlobalconfigsDir, #pragma warning disable CA1308 // Normalize strings to uppercase - $"{analysisLevelPropName}_{analysisLevelVersionString}_{analysisMode!.ToString()!.ToLowerInvariant()}.editorconfig", + var globalconfigFileName = $"{analysisLevelPropName}_{analysisLevelVersionString}_{analysisMode!.ToString()!.ToLowerInvariant()}"; #pragma warning restore CA1308 // Normalize strings to uppercase - title, + + if (warnAsError) + { + globalconfigFileName += "_warnaserror"; + title += " escalated to 'error' severity"; + description += " Enabled rules with 'warning' severity are escalated to 'error' severity to respect 'CodeAnalysisTreatWarningsAsErrors' MSBuild property."; + } + + CreateGlobalconfig( + analyzerGlobalconfigsDir, + $"{globalconfigFileName}.globalconfig", + title, description, + warnAsError, analysisMode, category, allRulesById, @@ -1158,34 +1159,37 @@ private static void Validate(string fileWithPath, string fileContents, List sortedRulesById, (ImmutableArray releaseTrackingData, Version version, bool isShippedVersion) releaseTrackingDataAndVersion) { - Debug.Assert(editorconfigFileName.EndsWith(".editorconfig", StringComparison.Ordinal)); + Debug.Assert(fileName.EndsWith(".globalconfig", StringComparison.Ordinal)); var text = GetGlobalconfigText( - editorconfigTitle, - editorconfigDescription, + title, + description, + warnAsError, analysisMode, category, sortedRulesById, releaseTrackingDataAndVersion); var directory = Directory.CreateDirectory(folder); #pragma warning disable CA1308 // Normalize strings to uppercase - Need to use 'ToLowerInvariant' for file names in non-Windows platforms - var editorconfigFilePath = Path.Combine(directory.FullName, editorconfigFileName.ToLowerInvariant()); + var configFilePath = Path.Combine(directory.FullName, fileName.ToLowerInvariant()); #pragma warning restore CA1308 // Normalize strings to uppercase - File.WriteAllText(editorconfigFilePath, text); + File.WriteAllText(configFilePath, text); return; // Local functions static string GetGlobalconfigText( - string editorconfigTitle, - string editorconfigDescription, + string title, + string description, + bool warnAsError, AnalysisMode analysisMode, string? category, SortedList sortedRulesById, @@ -1200,8 +1204,8 @@ void StartGlobalconfig() { result.AppendLine(@"# NOTE: Requires **VS2019 16.7** or later"); result.AppendLine(); - result.AppendLine($@"# {editorconfigTitle}"); - result.AppendLine($@"# Description: {editorconfigDescription}"); + result.AppendLine($@"# {title}"); + result.AppendLine($@"# Description: {description}"); result.AppendLine(); result.AppendLine($@"is_global = true"); result.AppendLine(); @@ -1240,6 +1244,11 @@ bool AddRule(DiagnosticDescriptor rule, string? category) } var (isEnabledByDefault, severity) = GetEnabledByDefaultAndSeverity(rule, analysisMode); + if (warnAsError && severity == DiagnosticSeverity.Warning && isEnabledByDefault) + { + severity = DiagnosticSeverity.Error; + } + if (rule.IsEnabledByDefault == isEnabledByDefault && severity == rule.DefaultSeverity) { @@ -1395,7 +1404,6 @@ static string GetCommonContents(string packageName, IOrderedEnumerable c } stringBuilder.Append(GetMSBuildContentForPropertyAndItemOptions()); - stringBuilder.Append(GetCodeAnalysisTreatWarningsAsErrorsTargetContents()); return stringBuilder.ToString(); } @@ -1443,8 +1451,14 @@ static string GetGlobalAnalyzerConfigTargetContents(string packageName, string? <_GlobalAnalyzerConfigAnalysisMode_{trimmedPackageName} Condition=""'$(_GlobalAnalyzerConfigAnalysisMode_{trimmedPackageName})' == 'AllDisabledByDefault'"">{nameof(AnalysisMode.None)} <_GlobalAnalyzerConfigAnalysisMode_{trimmedPackageName} Condition=""'$(_GlobalAnalyzerConfigAnalysisMode_{trimmedPackageName})' == ''"">{nameof(AnalysisMode.Default)} + + + $(CodeAnalysisTreatWarningsAsErrors) + + <_GlobalAnalyzerConfigFileName_{trimmedPackageName}_WarnAsErrorSuffix Condition=""'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'"">_warnaserror + - <_GlobalAnalyzerConfigFileName_{trimmedPackageName} Condition=""'$({packageVersionPropName})' != ''"">{analysisLevelPropName}_$({packageVersionPropName}.Replace(""."",""_""))_$(_GlobalAnalyzerConfigAnalysisMode_{trimmedPackageName}).editorconfig + <_GlobalAnalyzerConfigFileName_{trimmedPackageName} Condition=""'$({packageVersionPropName})' != ''"">{analysisLevelPropName}_$({packageVersionPropName}.Replace(""."",""_""))_$(_GlobalAnalyzerConfigAnalysisMode_{trimmedPackageName})$(_GlobalAnalyzerConfigFileName_{trimmedPackageName}_WarnAsErrorSuffix).globalconfig <_GlobalAnalyzerConfigFileName_{trimmedPackageName}>$(_GlobalAnalyzerConfigFileName_{trimmedPackageName}.ToLowerInvariant()) <_GlobalAnalyzerConfigDir_{trimmedPackageName} Condition=""'$(_GlobalAnalyzerConfigDir_{trimmedPackageName})' == ''"">$(MSBuildThisFileDirectory)config @@ -1580,23 +1594,6 @@ static void AddMSBuildContentForItemOptions(StringBuilder builder) } } - static string GetCodeAnalysisTreatWarningsAsErrorsTargetContents() - { - return $@" - - - - $(WarningsNotAsErrors);$(CodeAnalysisRuleIds) - $(WarningsAsErrors);$(CodeAnalysisRuleIds) - - -"; - } - static string GetPackageSpecificContents(string packageName) => packageName switch {