diff --git a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj
index d26639408e..61e8ad740e 100644
--- a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj
+++ b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj
@@ -125,6 +125,7 @@
+
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeType.cs b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeType.cs
index 038093e591..eb7838dfc5 100644
--- a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeType.cs
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeType.cs
@@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Linq;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Project;
@@ -72,15 +73,19 @@ namespace ICSharpCode.PackageManagement.EnvDTE
public virtual ProjectItem ProjectItem {
get {
if (ProjectContent.Project != null) {
- return new ProjectItem((MSBuildBasedProject)ProjectContent.Project, Class);
+ return new ProjectItem(ProjectContent, Class);
}
return null;
}
}
+ ///
+ /// Returns true if the current type matches the fully qualified name or any of its
+ /// base types are a match.
+ ///
public virtual bool IsDerivedFrom(string fullName)
{
- throw new NotImplementedException();
+ return Class.IsDerivedFrom(fullName);
}
}
}
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/IClassExtensions.cs b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/IClassExtensions.cs
new file mode 100644
index 0000000000..68d38b9081
--- /dev/null
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/IClassExtensions.cs
@@ -0,0 +1,43 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Linq;
+using ICSharpCode.SharpDevelop.Dom;
+
+namespace ICSharpCode.PackageManagement.EnvDTE
+{
+ public static class IClassExtensions
+ {
+ ///
+ /// Returns true if the class fully qualified name matches the name or
+ /// any class in the inheritance tree matches the name.
+ ///
+ public static bool IsDerivedFrom(this IClass c, string typeName)
+ {
+ if (c.FullyQualifiedName == typeName) {
+ return true;
+ }
+
+ if (TypeNameMatchesBaseType(c.BaseType, typeName)) {
+ return true;
+ }
+
+ return IsTypeInClassInheritanceTree(c, typeName);
+ }
+
+ static bool TypeNameMatchesBaseType(IReturnType baseType, string typeName)
+ {
+ return
+ (baseType != null) &&
+ (baseType.FullyQualifiedName == typeName);
+ }
+
+ static bool IsTypeInClassInheritanceTree(IClass c, string typeName)
+ {
+ return c
+ .ClassInheritanceTreeClassesOnly
+ .Any(inheritedClass => inheritedClass.FullyQualifiedName == typeName);
+ }
+ }
+}
diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/ProjectItem.cs b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/ProjectItem.cs
index ebdaccfff8..747dee441b 100644
--- a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/ProjectItem.cs
+++ b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/ProjectItem.cs
@@ -34,6 +34,11 @@ namespace ICSharpCode.PackageManagement.EnvDTE
{
}
+ internal ProjectItem(IProjectContent projectContent, IClass c)
+ : this((MSBuildBasedProject)projectContent.Project, c)
+ {
+ }
+
string GetKindFromFileProjectItemType()
{
if (IsDirectory) {
diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/CodeTypeTests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/CodeTypeTests.cs
index 0615a38957..4935c36043 100644
--- a/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/CodeTypeTests.cs
+++ b/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/CodeTypeTests.cs
@@ -46,7 +46,15 @@ namespace PackageManagement.Tests.EnvDTE
SDProject.FileProjectItem AddFileToProjectAndProjectContent(TestableProject project, string fileName)
{
helper.CompilationUnitHelper.SetFileName(fileName);
- return project.AddFile(fileName);
+ return project.AddFile(fileName);
+ }
+
+ ///
+ /// Classes at the end of the array are at the top of the inheritance tree.
+ ///
+ void AddClassInheritanceTree(params string[] classNames)
+ {
+ helper.AddClassInheritanceTreeClassesOnly(classNames);
}
[Test]
@@ -121,5 +129,70 @@ namespace PackageManagement.Tests.EnvDTE
Assert.AreEqual("test.cs", item.Name);
}
+
+ [Test]
+ public void IsDerivedFrom_ClassFullyQualifiedNameMatchesTypeNameBeingChecked_ReturnsTrue()
+ {
+ CreateProjectContent();
+ CreateClass("System.Web.Mvc.ActionResult");
+ CreateCodeType();
+
+ bool derivedFrom = codeType.IsDerivedFrom("System.Web.Mvc.ActionResult");
+
+ Assert.IsTrue(derivedFrom);
+ }
+
+ [Test]
+ public void IsDerivedFrom_ClassFullyQualifiedNameDoesNotMatcheTypeNameBeingChecked_ReturnsFalse()
+ {
+ CreateProjectContent();
+ CreateClass("TestClass");
+ AddClassInheritanceTree("System.Object");
+ CreateCodeType();
+
+ bool derivedFrom = codeType.IsDerivedFrom("System.Web.Mvc.ActionResult");
+
+ Assert.IsFalse(derivedFrom);
+ }
+
+ [Test]
+ public void IsDerivedFrom_ClassBaseTypeFullyQualifiedNameMatchesTypeName_ReturnsTrue()
+ {
+ CreateProjectContent();
+ CreateClass("CustomActionResult");
+ helper.AddBaseTypeToClass("System.Web.Mvc.ActionResult");
+ CreateCodeType();
+
+ bool derivedFrom = codeType.IsDerivedFrom("System.Web.Mvc.ActionResult");
+
+ Assert.IsTrue(derivedFrom);
+ }
+
+ [Test]
+ public void IsDerivedFrom_ClassHasTypeInClassInheritanceTreeButNotImmediateBaseType_ReturnsTrue()
+ {
+ CreateProjectContent();
+ CreateClass("CustomActionResult");
+ AddClassInheritanceTree("CustomActionResultBase", "System.Web.Mvc.ActionResult");
+ CreateCodeType();
+
+ bool derivedFrom = codeType.IsDerivedFrom("System.Web.Mvc.ActionResult");
+
+ Assert.IsTrue(derivedFrom);
+ }
+
+ [Test]
+ public void IsDerivedFrom_ClassHasClassInInheritanceTreeButNotImmediateParentAndClassBaseTypePropertyIsNotNull_ReturnsTrue()
+ {
+ CreateProjectContent();
+ CreateClass("CustomActionResult");
+ helper.AddBaseTypeToClass("CustomActionResultBase");
+ AddClassInheritanceTree("CustomActionResultBase", "System.Web.Mvc.ActionResult");
+ CreateCodeType();
+
+ bool derivedFrom = codeType.IsDerivedFrom("System.Web.Mvc.ActionResult");
+
+ Assert.IsTrue(derivedFrom);
+ }
}
}
diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ClassHelper.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ClassHelper.cs
index 55353ee3c7..124e4853a2 100644
--- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ClassHelper.cs
+++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ClassHelper.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using ICSharpCode.SharpDevelop.Dom;
using Rhino.Mocks;
@@ -66,13 +67,18 @@ namespace PackageManagement.Tests.Helpers
Class.Stub(c => c.BaseTypes).Return(baseTypes);
}
- IReturnType CreateBaseType(IClass baseTypeClass, string baseTypeFullName, string baseTypeDotNetName)
+ ReturnTypeHelper CreateBaseTypeHelper(IClass baseTypeClass, string baseTypeFullName, string baseTypeDotNetName)
{
var returnTypeHelper = new ReturnTypeHelper();
returnTypeHelper.CreateReturnType(baseTypeFullName);
returnTypeHelper.AddUnderlyingClass(baseTypeClass);
returnTypeHelper.AddDotNetName(baseTypeDotNetName);
- return returnTypeHelper.ReturnType;
+ return returnTypeHelper;
+ }
+
+ IReturnType CreateBaseType(IClass baseTypeClass, string baseTypeFullName, string baseTypeDotNetName)
+ {
+ return CreateBaseTypeHelper(baseTypeClass, baseTypeFullName, baseTypeDotNetName).ReturnType;
}
public void AddClassToClassBaseTypes(string fullName)
@@ -185,5 +191,28 @@ namespace PackageManagement.Tests.Helpers
{
Class.Stub(c => c.DotNetName).Return(className);
}
+
+ ///
+ /// Classes at the end of the array are at the top of the inheritance tree.
+ ///
+ public void AddClassInheritanceTreeClassesOnly(params string[] classNames)
+ {
+ List classes = CreateClassInheritanceTree(classNames);
+ Class.Stub(c => c.ClassInheritanceTreeClassesOnly).Return(classes);
+ }
+
+ List CreateClassInheritanceTree(string[] classNames)
+ {
+ return classNames
+ .Select(name => CreateClassHelperWithPublicClass(name).Class)
+ .ToList();
+ }
+
+ ClassHelper CreateClassHelperWithPublicClass(string name)
+ {
+ var classHelper = new ClassHelper();
+ classHelper.CreatePublicClass(name);
+ return classHelper;
+ }
}
}