using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.FxCop.Sdk;
using System.Runtime.CompilerServices;
using System.Reflection;
namespace MSSWC.CodeAnalysis.MaintainabilityRules
{
/// <summary>
/// Generate warning/error when method signature of an extension method matches one that already exists on the
/// base class.
/// </summary>
internal sealed class DoNotDuplicateBaseClassMethodSignatureInExtensionMethod : MaintainabilityRule
{
/// <summary>
/// Initializes a new instance of the <see cref="DoNotDuplicateBaseClassMethodSignatureInExtensionMethod"/> class.
/// </summary>
public DoNotDuplicateBaseClassMethodSignatureInExtensionMethod()
: base("DoNotDuplicateBaseClassMethodSignatureInExtensionMethod")
{
}
/// <summary>
/// Members has an attribute of the given type.
/// </summary>
/// <param name="member">The member.</param>
/// <param name="typeToCheck">The type to check.</param>
/// <returns>True if member has an attribute of typeToCheck</returns>
private static bool MemberHasAttribute(Member member, Type typeToCheck)
{
foreach (AttributeNode attrib in member.Attributes)
{
if (attrib.Type.FullName == typeToCheck.FullName)
{
return true;
}
}
return false;
}
/// <summary>
/// Returns whether the baseType has a method signature that matches the passed in methodSignature.
/// </summary>
/// <param name="baseType">Type of the base.</param>
/// <param name="methodSignature">The method signature.</param>
/// <returns>True if baseType has a method signature that matches methodSignature.</returns>
private static bool TypeHasMethodSignature(TypeNode baseType, string methodSignature)
{
var result = from m in baseType.Members
where m.FullName == methodSignature
select m.FullName;
return result.Count() > 0;
}
/// <summary>
/// Checks the specified member for problems.
/// </summary>
/// <param name="member">The member.</param>
/// <returns></returns>
public override ProblemCollection Check(Member member)
{
Method method = member as Method;
if (method != null)
{
if (MemberHasAttribute(member, typeof(ExtensionAttribute)))
{
// Get first parameter's type which is the type that we are extending
TypeNode node = method.Parameters[0].Type;
// build array of the parameters for the extension method
string parameters = "";
for (int i = 1; i < method.Parameters.Count; i++)
{
parameters += method.Parameters[i].Type.FullName + ",";
}
parameters = parameters.Trim(',');
// build method signature string
string methodSignature = node.FullName + "." + member.Name.Name;
if (!string.IsNullOrEmpty(parameters))
{
methodSignature += "(" + parameters + ")";
}
// ensure method signature does not already exist on base class
if (TypeHasMethodSignature(node, methodSignature))
{
Resolution resolution = GetNamedResolution("Default",
new object[] { member.FullName, methodSignature });
Problems.Add(new Problem(resolution, method.SourceContext));
}
}
}
return Problems;
}
}
}