|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared.FileSystem;
#nullable disable
namespace Microsoft.Build.Tasks
{
/// <summary>
/// Determines which file, if any, to be used as the code analysis rule set based
/// on the supplied code analysis properties.
/// </summary>
public sealed class ResolveCodeAnalysisRuleSet : TaskExtension
{
#region Properties
/// <summary>
/// The desired code analysis rule set file. May be a simple name, relative
/// path, or full path.
/// </summary>
public string CodeAnalysisRuleSet { get; set; }
/// <summary>
/// The set of additional directories to search for code analysis rule set files.
/// </summary>
public string[] CodeAnalysisRuleSetDirectories { get; set; }
/// <summary>
/// The location of the project currently being built.
/// </summary>
public string MSBuildProjectDirectory { get; set; }
/// <summary>
/// The location of the resolved rule set file. May be null if the file
/// does not exist on disk.
/// </summary>
[Output]
public string ResolvedCodeAnalysisRuleSet { get; private set; }
/// <summary>
/// Runs the task.
/// </summary>
/// <returns>True if the task succeeds without errors; false otherwise.</returns>
public override bool Execute()
{
ResolvedCodeAnalysisRuleSet = GetResolvedRuleSetPath();
return !Log.HasLoggedErrors;
}
/// <summary>
/// Computes the resolved rule set path.
///
/// There are four cases: null, file name, relative path, and full path.
///
/// If we were given no value for the ruleset, simply return null.
///
/// For full path we return the string as it is.
///
/// A simple file name can refer to either a file in the MSBuild project directory
/// or a file in the rule set search paths. In the former case we return the string as-is.
/// In the latter case, we create a full path by prepending the first rule set search path
/// where the file is found.
///
/// For relative paths we return the string as-is.
///
/// In all cases, we return null if the file does not actual exist.
/// </summary>
/// <returns>The full or relative path to the rule set, or null if the file does not exist.</returns>
private string GetResolvedRuleSetPath()
{
if (string.IsNullOrEmpty(CodeAnalysisRuleSet))
{
return null;
}
if (CodeAnalysisRuleSet == Path.GetFileName(CodeAnalysisRuleSet))
{
// This is a simple file name.
// Check if the file exists in the MSBuild project directory.
if (!string.IsNullOrEmpty(MSBuildProjectDirectory))
{
string fullName = Path.Combine(MSBuildProjectDirectory, CodeAnalysisRuleSet);
if (FileSystems.Default.FileExists(fullName))
{
return CodeAnalysisRuleSet;
}
}
// Try the rule set directories if we have some.
if (CodeAnalysisRuleSetDirectories != null)
{
foreach (string directory in CodeAnalysisRuleSetDirectories)
{
string fullName = Path.Combine(directory, CodeAnalysisRuleSet);
if (FileSystems.Default.FileExists(fullName))
{
return fullName;
}
}
}
}
else if (!Path.IsPathRooted(CodeAnalysisRuleSet))
{
// This is a path relative to the project.
if (!string.IsNullOrEmpty(MSBuildProjectDirectory))
{
string fullName = Path.Combine(MSBuildProjectDirectory, CodeAnalysisRuleSet);
if (FileSystems.Default.FileExists(fullName))
{
return CodeAnalysisRuleSet;
}
}
}
else if (FileSystems.Default.FileExists(CodeAnalysisRuleSet))
{
// This is a full path.
return CodeAnalysisRuleSet;
}
// We can't resolve the rule set to any existing file.
Log.LogWarningWithCodeFromResources("Compiler.UnableToFindRuleSet", CodeAnalysisRuleSet);
return null;
}
#endregion
}
}
|