问题描述
我正在将大型项目从 net framework 移植到 net5,这带来了大量警告。我想让所有以 SYSLIB
开头的警告都是错误的。
一种可能的解决方案是在 WarnAsError
中列出所有警告,但对于这样一个简单的任务来说,写太多了,而且如果出现另一个警告(例如 syslib00013),新版本将是警告,而不是错误。
<WarnAsError>($WarnAsError);SYSLIB0001;SYSLIB0002;etc</WarnAsError>
写<WarnAsError>true</WarnAsError>
不是一种选择
尝试编写 <WarningsAsErrors>$(WarnAsError);SYSLIB</WarningsAsErrors>
没有帮助
解决方法
一段时间后,我找到了一种很好且干净的方法。
我不得不写UsingTask
<UsingTask TaskName="ExpandRanges"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll"
>
<ParameterGroup>
<Ranges ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<Result ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" />
</ParameterGroup>
<Task>
<Using Namespace="System.Linq" />
<Using Namespace="System.Collections.Generic" />
<Code Type="Fragment" Language="cs">
<![CDATA[
const string prefixName = "Prefix";
var list = new List<ITaskItem>(Ranges.Length);
foreach (var range in Ranges)
{
string include = range.ToString();
string prefix = range.GetMetadata(prefixName);
if (string.IsNullOrEmpty(prefix))
{
Log.LogWarning($"Metadata {prefixName} was not found in {include} and will be ignored");
continue;
}
if (include.All(char.IsDigit))
{
list.Add(new TaskItem(prefix + include));
}
else if (include.Split('-') is { Length: 2 } splitted)
{
int start = int.Parse(splitted[0]);
int stop = int.Parse(splitted[1]);
for (int i = start; i < stop + 1; i++)
{
list.Add(new TaskItem($"{prefix}{i:0000}"));
}
}
else
{
Log.LogWarning($"{include} have incorrect format and will be ignored");
}
}
Result = list.ToArray();
]]>
</Code>
</Task>
</UsingTask>
还有Target
<Target Name="ExpandWarningsAsErrorsRange"
BeforeTargets="CoreCompile"
Inputs="@(WarningsAsErrorsRange)"
Outputs="$(WarningsAsErrors)"
>
<ExpandRanges Ranges="@(WarningsAsErrorsRange)">
<Output ItemName="_WarnRange" TaskParameter="Result" />
</ExpandRanges>
<PropertyGroup>
<WarningsAsErrors>$(WarningsAsErrors);@(_WarnRange)</WarningsAsErrors>
</PropertyGroup>
</Target>
这两个东西都应该位于 Directory.Build.targets
中,项目只需要包含特定的警告
<ItemGroup>
<WarningsAsErrorsRange Include="0000-0002" Prefix="SYSLIB" />
<WarningsAsErrorsRange Include="0006" Prefix="SYSLIB" />
</ItemGroup>
这个解决方案有一些缺陷,比如它不支持 ItemGroup 中的 Exclude
但对我来说已经足够了。