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; + } } }