diff --git a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj index a8a2cedd71..2e5b3dc0bc 100644 --- a/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj +++ b/src/AddIns/Misc/PackageManagement/Project/PackageManagement.csproj @@ -122,6 +122,8 @@ + + diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeNamespace.cs b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeNamespace.cs index 9c93be2971..a5b323dff9 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeNamespace.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/CodeNamespace.cs @@ -40,7 +40,7 @@ namespace ICSharpCode.PackageManagement.EnvDTE get { return namespaceName.LastPart; } } - public CodeElements Members { + public virtual CodeElements Members { get { return new CodeElementsInNamespace(projectContent, namespaceName); } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/FileCodeModelCodeElements.cs b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/FileCodeModelCodeElements.cs index 2ee8af40d5..39bb3f4636 100644 --- a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/FileCodeModelCodeElements.cs +++ b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/FileCodeModelCodeElements.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Project; @@ -11,6 +12,7 @@ namespace ICSharpCode.PackageManagement.EnvDTE public class FileCodeModelCodeElements : CodeElementsList { ICompilationUnit compilationUnit; + List fileCodeModelNamespaces = new List(); public FileCodeModelCodeElements(ICompilationUnit compilationUnit) { @@ -23,6 +25,7 @@ namespace ICSharpCode.PackageManagement.EnvDTE foreach (IUsing namespaceUsing in GetNamespaceImports()) { AddNamespaceImport(namespaceUsing); } + AddClasses(); } IList GetNamespaceImports() @@ -36,5 +39,35 @@ namespace ICSharpCode.PackageManagement.EnvDTE { AddCodeElement(new CodeImport(import)); } + + void AddClasses() + { + foreach (IClass c in compilationUnit.Classes) { + FileCodeModelCodeNamespace codeNamespace = GetOrCreateFileCodeModelNamespace(c); + codeNamespace.AddClass(compilationUnit.ProjectContent, c); + } + } + + FileCodeModelCodeNamespace GetOrCreateFileCodeModelNamespace(IClass c) + { + var codeNamespace = FindFileCodeModelNamespace(c); + if (codeNamespace != null) { + return codeNamespace; + } + return CreateFileCodeModelNamespace(c); + } + + FileCodeModelCodeNamespace FindFileCodeModelNamespace(IClass c) + { + return fileCodeModelNamespaces.FirstOrDefault(ns => ns.FullName == c.Namespace); + } + + FileCodeModelCodeNamespace CreateFileCodeModelNamespace(IClass c) + { + var codeNamespace = new FileCodeModelCodeNamespace(compilationUnit.ProjectContent, c.Namespace); + AddCodeElement(codeNamespace); + fileCodeModelNamespaces.Add(codeNamespace); + return codeNamespace; + } } } diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/FileCodeModelCodeNamespace.cs b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/FileCodeModelCodeNamespace.cs new file mode 100644 index 0000000000..12fb129859 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/FileCodeModelCodeNamespace.cs @@ -0,0 +1,38 @@ +// 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 ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PackageManagement.EnvDTE +{ + /// + /// File code model namespaces take the full name of the namespace that a class + /// is inside. So for the FileCodeModelNamespace class the CodeNamespace.Name + /// would be ICSharpCode.PackageManagement.EnvDTE. + /// This differs from the CodeModel CodeNamespace which breaks up the namespaces into + /// parts. + /// + public class FileCodeModelCodeNamespace : CodeNamespace + { + FileCodeModelCodeNamespaceMembers members = new FileCodeModelCodeNamespaceMembers(); + + public FileCodeModelCodeNamespace(IProjectContent projectContent, string namespaceName) + : base(projectContent, namespaceName) + { + } + + public override string Name { + get { return base.FullName; } + } + + public override CodeElements Members { + get { return members; } + } + + public void AddClass(IProjectContent projectContent, IClass c) + { + members.AddClass(projectContent, c); + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/FileCodeModelCodeNamespaceMembers.cs b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/FileCodeModelCodeNamespaceMembers.cs new file mode 100644 index 0000000000..99e00c8c58 --- /dev/null +++ b/src/AddIns/Misc/PackageManagement/Project/Src/EnvDTE/FileCodeModelCodeNamespaceMembers.cs @@ -0,0 +1,21 @@ +// 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 ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PackageManagement.EnvDTE +{ + public class FileCodeModelCodeNamespaceMembers : CodeElementsList + { + public FileCodeModelCodeNamespaceMembers() + { + } + + public void AddClass(IProjectContent projectContent, IClass c) + { + var codeClass = new CodeClass2(projectContent, c); + AddCodeElement(codeClass); + } + } +} diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/FileCodeModel2Tests.cs b/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/FileCodeModel2Tests.cs index ec7dcb8d5a..8f78b1b84e 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/FileCodeModel2Tests.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/EnvDTE/FileCodeModel2Tests.cs @@ -56,6 +56,11 @@ namespace PackageManagement.Tests.EnvDTE return fileCodeModel.CodeElements.FirstCodeImportOrDefault(); } + CodeNamespace GetFirstCodeNamespaceFromCodeElements() + { + return fileCodeModel.CodeElements.FirstCodeNamespaceOrDefault(); + } + void AddNamespaceToCompilationUnit(string namespaceName) { compilationUnitHelper.AddNamespace(namespaceName); @@ -65,7 +70,21 @@ namespace PackageManagement.Tests.EnvDTE { compilationUnitHelper.AddNamespaceAlias(alias, namespaceName); } - + + void AddClassToCompilationUnit(string namespaceName, string className) + { + var classHelper = new ClassHelper(); + classHelper.CreatePublicClass(className); + classHelper.AddNamespaceUsingScopeToClass(namespaceName); + classHelper.AddClassNamespace(namespaceName); + compilationUnitHelper.AddClass(classHelper.Class); + } + + CodeNamespace GetLastCodeNamespaceFromCodeElements() + { + return fileCodeModel.CodeElements.LastCodeNamespaceOrDefault(); + } + [Test] public void CodeElements_OneNamespaceInFile_FileNameUsedToGetCompilationUnit() { @@ -116,5 +135,65 @@ namespace PackageManagement.Tests.EnvDTE namespaceCreator.AssertWasCalled(creator => creator.AddNamespace(compilationUnitHelper.CompilationUnit, "System.Xml")); } + + [Test] + public void CodeElements_OneClassInFileWithNamespace_ReturnsOneCodeNamespace() + { + CreateProjectWithOneFile(); + CreateCompilationUnitForFileProjectItem(); + AddClassToCompilationUnit("Test.CodeModel", "Test.CodeModel.Class1"); + CreateFileCodeModel(); + + CodeNamespace ns = GetFirstCodeNamespaceFromCodeElements(); + + Assert.AreEqual("Test.CodeModel", ns.Name); + } + + [Test] + public void CodeElements_OneClassInFileWithNamespace_ReturnsOneClassInsideCodeNamespace() + { + CreateProjectWithOneFile(); + CreateCompilationUnitForFileProjectItem(); + AddClassToCompilationUnit("Test.CodeModel", "Test.CodeModel.Class1"); + CreateFileCodeModel(); + + CodeNamespace ns = GetFirstCodeNamespaceFromCodeElements(); + CodeClass2 codeClass = ns.Members.FirstCodeClass2OrDefault(); + + Assert.AreEqual("Test.CodeModel.Class1", codeClass.FullName); + } + + [Test] + public void CodeElements_TwoClassesInFileWithNamespace_ReturnsTwoClassesInsideCodeNamespace() + { + CreateProjectWithOneFile(); + CreateCompilationUnitForFileProjectItem(); + AddClassToCompilationUnit("Test.CodeModel", "Test.CodeModel.Class1"); + AddClassToCompilationUnit("Test.CodeModel", "Test.CodeModel.Class2"); + CreateFileCodeModel(); + + CodeNamespace ns = GetFirstCodeNamespaceFromCodeElements(); + CodeClass2 codeClass1 = ns.Members.FirstCodeClass2OrDefault(); + CodeClass2 codeClass2 = ns.Members.LastCodeClass2OrDefault(); + + Assert.AreEqual("Test.CodeModel.Class1", codeClass1.FullName); + Assert.AreEqual("Test.CodeModel.Class2", codeClass2.FullName); + } + + [Test] + public void CodeElements_TwoClassesInFileEachWithDifferentNamespace_ReturnsTwoCodeNamespaces() + { + CreateProjectWithOneFile(); + CreateCompilationUnitForFileProjectItem(); + AddClassToCompilationUnit("Test.CodeModel1", "Test.CodeModel.Class1"); + AddClassToCompilationUnit("Test.CodeModel2", "Test.CodeModel.Class2"); + CreateFileCodeModel(); + + CodeNamespace ns1 = GetFirstCodeNamespaceFromCodeElements(); + CodeNamespace ns2 = GetLastCodeNamespaceFromCodeElements(); + + Assert.AreEqual("Test.CodeModel1", ns1.Name); + Assert.AreEqual("Test.CodeModel2", ns2.Name); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ClassHelper.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ClassHelper.cs index f79cbd8e5b..0d32a8e6b8 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ClassHelper.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/ClassHelper.cs @@ -172,5 +172,13 @@ namespace PackageManagement.Tests.Helpers { Class.Stub(c => c.IsPartial).Return(true); } + + public void AddNamespaceUsingScopeToClass(string namespaceName) + { + var usingScopeHelper = new UsingScopeHelper(); + usingScopeHelper.SetNamespaceName(namespaceName); + + Class.Stub(c => c.UsingScope).Return(usingScopeHelper.UsingScope); + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/CodeElementsExtensions.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/CodeElementsExtensions.cs index e55fa0c2d9..87e6749f84 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/CodeElementsExtensions.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/CodeElementsExtensions.cs @@ -83,5 +83,10 @@ namespace PackageManagement.Tests.Helpers { return codeElements.FirstOrDefault() as CodeImport; } + + public static CodeClass2 LastCodeClass2OrDefault(this CodeElements codeElements) + { + return codeElements.LastOrDefault() as CodeClass2; + } } } diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/CompilationUnitHelper.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/CompilationUnitHelper.cs index 3ff65181f7..73c4284b78 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/CompilationUnitHelper.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/CompilationUnitHelper.cs @@ -14,6 +14,7 @@ namespace PackageManagement.Tests.Helpers public FakeCodeGenerator FakeCodeGenerator = new FakeCodeGenerator(); public List Classes = new List(); public UsingScopeHelper UsingScopeHelper = new UsingScopeHelper(); + public ProjectContentHelper ProjectContentHelper = new ProjectContentHelper(); public CompilationUnitHelper() { @@ -23,6 +24,7 @@ namespace PackageManagement.Tests.Helpers CompilationUnit.Stub(unit => unit.Language).Return(language); CompilationUnit.Stub(unit => unit.Classes).Return(Classes); CompilationUnit.Stub(unit => unit.UsingScope).Return(UsingScopeHelper.UsingScope); + CompilationUnit.Stub(unit => unit.ProjectContent).Return(ProjectContentHelper.ProjectContent); } public void SetFileName(string fileName) diff --git a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/UsingScopeHelper.cs b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/UsingScopeHelper.cs index b6674a563d..be4cf51948 100644 --- a/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/UsingScopeHelper.cs +++ b/src/AddIns/Misc/PackageManagement/Test/Src/Helpers/UsingScopeHelper.cs @@ -37,5 +37,10 @@ namespace PackageManagement.Tests.Helpers usingHelper.AddNamespaceAlias(alias, namespaceName); Usings.Add(usingHelper.Using); } + + public void SetNamespaceName(string namespaceName) + { + UsingScope.Stub(u => u.NamespaceName).Return(namespaceName); + } } }