diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/AddInAssemblyName.cs b/src/AddIns/Misc/TextTemplating/Project/Src/AddInAssemblyName.cs new file mode 100644 index 0000000000..46ea3c69e8 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/AddInAssemblyName.cs @@ -0,0 +1,36 @@ +// 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.TextTemplating +{ + public class AddInAssemblyName + { + string assemblyShortName; + + public AddInAssemblyName(string assemblyFullName) + { + GetAssemblyShortName(assemblyFullName); + } + + void GetAssemblyShortName(string assemblyFullName) + { + if (assemblyFullName != null) { + var domAssemblyName = new DomAssemblyName(assemblyFullName); + assemblyShortName = "ICSharpCode." + domAssemblyName.ShortName; + } + } + + public bool Matches(IAddIn addIn) + { + return CompareIgnoringCase(assemblyShortName, addIn.PrimaryIdentity); + } + + bool CompareIgnoringCase(string a, string b) + { + return String.Equals(a, b, StringComparison.OrdinalIgnoreCase); + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/AddInAssemblyRuntime.cs b/src/AddIns/Misc/TextTemplating/Project/Src/AddInAssemblyRuntime.cs new file mode 100644 index 0000000000..fb894c869a --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/AddInAssemblyRuntime.cs @@ -0,0 +1,60 @@ +// 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; + +namespace ICSharpCode.TextTemplating +{ + public class AddInAssemblyRuntime + { + string fileName; + IAddIn addIn; + IAddInRuntime runtime; + + public AddInAssemblyRuntime(IAddIn addIn) + { + this.addIn = addIn; + GetFileName(); + GetRuntime(); + } + + void GetFileName() + { + string fileNameWithoutExtension = GetFileNameWithoutExtension(); + fileName = fileNameWithoutExtension + ".dll"; + } + + string GetFileNameWithoutExtension() + { + string id = addIn.PrimaryIdentity; + int index = id.IndexOf(".", StringComparison.OrdinalIgnoreCase); + return id.Substring(index + 1); + } + + public string FileName { + get { return fileName; } + } + + void GetRuntime() + { + runtime = addIn + .GetRuntimes() + .SingleOrDefault(r => Matches(r.Assembly)); + } + + public bool Matches(string runtimeFileName) + { + return CompareIgnoringCase(runtimeFileName, this.fileName); + } + + bool CompareIgnoringCase(string a, string b) + { + return String.Equals(a, b, StringComparison.OrdinalIgnoreCase); + } + + public IAddInRuntime Runtime { + get { return runtime; } + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/IAddIn.cs b/src/AddIns/Misc/TextTemplating/Project/Src/IAddIn.cs new file mode 100644 index 0000000000..c87c72fe99 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/IAddIn.cs @@ -0,0 +1,16 @@ +// 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.Collections.Generic; +using System.Reflection; + +namespace ICSharpCode.TextTemplating +{ + public interface IAddIn + { + string PrimaryIdentity { get; } + + IEnumerable GetRuntimes(); + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/IAddInRuntime.cs b/src/AddIns/Misc/TextTemplating/Project/Src/IAddInRuntime.cs new file mode 100644 index 0000000000..ffedeae72d --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/IAddInRuntime.cs @@ -0,0 +1,14 @@ +// 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.Reflection; + +namespace ICSharpCode.TextTemplating +{ + public interface IAddInRuntime + { + string Assembly { get; } + Assembly LoadedAssembly { get; } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/IAddInTree.cs b/src/AddIns/Misc/TextTemplating/Project/Src/IAddInTree.cs new file mode 100644 index 0000000000..8ec9b72aa3 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/IAddInTree.cs @@ -0,0 +1,13 @@ +// 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.Collections.Generic; + +namespace ICSharpCode.TextTemplating +{ + public interface IAddInTree + { + IEnumerable GetAddIns(); + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/IAppDomain.cs b/src/AddIns/Misc/TextTemplating/Project/Src/IAppDomain.cs new file mode 100644 index 0000000000..e5fdb28450 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/IAppDomain.cs @@ -0,0 +1,12 @@ +// 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; + +namespace ICSharpCode.TextTemplating +{ + public interface IAppDomain + { + event ResolveEventHandler AssemblyResolve; + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/ITextTemplatingAssemblyPathResolver.cs b/src/AddIns/Misc/TextTemplating/Project/Src/ITextTemplatingAssemblyPathResolver.cs new file mode 100644 index 0000000000..809cf9d827 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/ITextTemplatingAssemblyPathResolver.cs @@ -0,0 +1,12 @@ +// 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; + +namespace ICSharpCode.TextTemplating +{ + public interface ITextTemplatingAssemblyPathResolver + { + string ResolvePath(string assemblyReference); + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/ITextTemplatingAssemblyResolver.cs b/src/AddIns/Misc/TextTemplating/Project/Src/ITextTemplatingAssemblyResolver.cs index 9b22085132..ceecaebf0f 100644 --- a/src/AddIns/Misc/TextTemplating/Project/Src/ITextTemplatingAssemblyResolver.cs +++ b/src/AddIns/Misc/TextTemplating/Project/Src/ITextTemplatingAssemblyResolver.cs @@ -5,8 +5,8 @@ using System; namespace ICSharpCode.TextTemplating { - public interface ITextTemplatingAssemblyResolver + public interface ITextTemplatingAssemblyResolver : IDisposable { - string Resolve(string assemblyReference); + string ResolvePath(string assemblyReference); } } diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/ITextTemplatingHostAppDomainAssemblyResolver.cs b/src/AddIns/Misc/TextTemplating/Project/Src/ITextTemplatingHostAppDomainAssemblyResolver.cs new file mode 100644 index 0000000000..b3a6555a97 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/ITextTemplatingHostAppDomainAssemblyResolver.cs @@ -0,0 +1,11 @@ +// 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; + +namespace ICSharpCode.TextTemplating +{ + public interface ITextTemplatingHostAppDomainAssemblyResolver : IDisposable + { + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAddIn.cs b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAddIn.cs new file mode 100644 index 0000000000..6cfac85692 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAddIn.cs @@ -0,0 +1,32 @@ +// 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.Collections.Generic; +using System.Reflection; + +using ICSharpCode.Core; + +namespace ICSharpCode.TextTemplating +{ + public class TextTemplatingAddIn : IAddIn + { + AddIn addIn; + + public TextTemplatingAddIn(AddIn addIn) + { + this.addIn = addIn; + } + + public string PrimaryIdentity { + get { return this.addIn.Manifest.PrimaryIdentity; } + } + + public IEnumerable GetRuntimes() + { + foreach (Runtime runtime in this.addIn.Runtimes) { + yield return new TextTemplatingAddInRuntime(runtime); + } + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAddInRuntime.cs b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAddInRuntime.cs new file mode 100644 index 0000000000..9b17e1e193 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAddInRuntime.cs @@ -0,0 +1,27 @@ +// 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.Reflection; +using ICSharpCode.Core; + +namespace ICSharpCode.TextTemplating +{ + public class TextTemplatingAddInRuntime : IAddInRuntime + { + Runtime runtime; + + public TextTemplatingAddInRuntime(Runtime runtime) + { + this.runtime = runtime; + } + + public string Assembly { + get { return runtime.Assembly; } + } + + public Assembly LoadedAssembly { + get { return runtime.LoadedAssembly; } + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAddInTree.cs b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAddInTree.cs new file mode 100644 index 0000000000..c50fd3a5c4 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAddInTree.cs @@ -0,0 +1,19 @@ +// 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.Collections.Generic; +using ICSharpCode.Core; + +namespace ICSharpCode.TextTemplating +{ + public class TextTemplatingAddInTree : IAddInTree + { + public IEnumerable GetAddIns() + { + foreach (AddIn addIn in AddInTree.AddIns) { + yield return new TextTemplatingAddIn(addIn); + } + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAssemblyPathResolver.cs b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAssemblyPathResolver.cs new file mode 100644 index 0000000000..c3147abc4c --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAssemblyPathResolver.cs @@ -0,0 +1,86 @@ +// 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.IO; +using ICSharpCode.SharpDevelop.Project; + +namespace ICSharpCode.TextTemplating +{ + public class TextTemplatingAssemblyPathResolver : ITextTemplatingAssemblyPathResolver + { + IProject project; + IAssemblyParserService assemblyParserService; + ITextTemplatingPathResolver pathResolver; + + public TextTemplatingAssemblyPathResolver( + IProject project, + IAssemblyParserService assemblyParserService, + ITextTemplatingPathResolver pathResolver) + { + this.project = project; + this.assemblyParserService = assemblyParserService; + this.pathResolver = pathResolver; + } + + public TextTemplatingAssemblyPathResolver(IProject project) + : this( + project, + new TextTemplatingAssemblyParserService(), + new TextTemplatingPathResolver()) + { + } + + public string ResolvePath(string assemblyReference) + { + assemblyReference = pathResolver.ResolvePath(assemblyReference); + if (Path.IsPathRooted(assemblyReference)) { + return assemblyReference; + } + + string resolvedAssemblyFileName = ResolveAssemblyFromProject(assemblyReference); + if (resolvedAssemblyFileName == null) { + resolvedAssemblyFileName = ResolveAssemblyFromGac(assemblyReference); + } + if (resolvedAssemblyFileName != null) { + return resolvedAssemblyFileName; + } + return assemblyReference; + } + + string ResolveAssemblyFromProject(string assemblyReference) + { + foreach (ReferenceProjectItem refProjectItem in project.GetItemsOfType(ItemType.Reference)) { + if (IsMatch(refProjectItem, assemblyReference)) { + return refProjectItem.FileName; + } + } + return null; + } + + bool IsMatch(ReferenceProjectItem refProjectItem, string assemblyReference) + { + return String.Equals(refProjectItem.Include, assemblyReference, StringComparison.InvariantCultureIgnoreCase); + } + + string ResolveAssemblyFromGac(string assemblyReference) + { + IReflectionProjectContent projectContent = GetProjectContent(assemblyReference); + if (projectContent != null) { + return projectContent.AssemblyLocation; + } + return null; + } + + IReflectionProjectContent GetProjectContent(string assemblyReference) + { + var reference = new ReferenceProjectItem(project, assemblyReference); + return GetProjectContent(reference); + } + + IReflectionProjectContent GetProjectContent(ReferenceProjectItem refProjectItem) + { + return assemblyParserService.GetReflectionProjectContentForReference(refProjectItem); + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAssemblyResolver.cs b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAssemblyResolver.cs index a47bc89ded..c0fad3574a 100644 --- a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAssemblyResolver.cs +++ b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingAssemblyResolver.cs @@ -9,83 +9,32 @@ namespace ICSharpCode.TextTemplating { public class TextTemplatingAssemblyResolver : ITextTemplatingAssemblyResolver { - IProject project; - IAssemblyParserService assemblyParserService; - ITextTemplatingPathResolver pathResolver; - - public TextTemplatingAssemblyResolver( - IProject project, - IAssemblyParserService assemblyParserService, - ITextTemplatingPathResolver pathResolver) - { - this.project = project; - this.assemblyParserService = assemblyParserService; - this.pathResolver = pathResolver; - } + ITextTemplatingAssemblyPathResolver assemblyPathResolver; + ITextTemplatingHostAppDomainAssemblyResolver appDomainAssemblyResolver; public TextTemplatingAssemblyResolver(IProject project) : this( - project, - new TextTemplatingAssemblyParserService(), - new TextTemplatingPathResolver()) + new TextTemplatingAssemblyPathResolver(project), + new TextTemplatingHostAppDomainAssemblyResolver()) { } - public string Resolve(string assemblyReference) - { - assemblyReference = ResolvePath(assemblyReference); - if (Path.IsPathRooted(assemblyReference)) { - return assemblyReference; - } - - string resolvedAssemblyFileName = ResolveAssemblyFromProject(assemblyReference); - if (resolvedAssemblyFileName == null) { - resolvedAssemblyFileName = ResolveAssemblyFromGac(assemblyReference); - } - if (resolvedAssemblyFileName != null) { - return resolvedAssemblyFileName; - } - return assemblyReference; - } - - string ResolvePath(string assemblyReference) - { - return pathResolver.ResolvePath(assemblyReference); - } - - string ResolveAssemblyFromProject(string assemblyReference) - { - foreach (ReferenceProjectItem refProjectItem in project.GetItemsOfType(ItemType.Reference)) { - if (IsMatch(refProjectItem, assemblyReference)) { - return refProjectItem.FileName; - } - } - return null; - } - - bool IsMatch(ReferenceProjectItem refProjectItem, string assemblyReference) - { - return String.Equals(refProjectItem.Include, assemblyReference, StringComparison.InvariantCultureIgnoreCase); - } - - string ResolveAssemblyFromGac(string assemblyReference) + public TextTemplatingAssemblyResolver( + ITextTemplatingAssemblyPathResolver assemblyPathResolver, + ITextTemplatingHostAppDomainAssemblyResolver appDomainAssemblyResolver) { - IReflectionProjectContent projectContent = GetProjectContent(assemblyReference); - if (projectContent != null) { - return projectContent.AssemblyLocation; - } - return null; + this.assemblyPathResolver = assemblyPathResolver; + this.appDomainAssemblyResolver = appDomainAssemblyResolver; } - IReflectionProjectContent GetProjectContent(string assemblyReference) + public string ResolvePath(string assemblyReference) { - var reference = new ReferenceProjectItem(project, assemblyReference); - return GetProjectContent(reference); + return assemblyPathResolver.ResolvePath(assemblyReference); } - IReflectionProjectContent GetProjectContent(ReferenceProjectItem refProjectItem) + public void Dispose() { - return assemblyParserService.GetReflectionProjectContentForReference(refProjectItem); + appDomainAssemblyResolver.Dispose(); } } } diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingCustomTool.cs b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingCustomTool.cs index 7bcc663a88..4376383c64 100644 --- a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingCustomTool.cs +++ b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingCustomTool.cs @@ -13,12 +13,8 @@ namespace ICSharpCode.TextTemplating protected TextTemplatingHost CreateTextTemplatingHost(IProject project) { - var appDomainFactory = new TextTemplatingAppDomainFactory(); - string applicationBase = GetAssemblyBaseLocation(); - var assemblyResolver = new TextTemplatingAssemblyResolver(project); - var textTemplatingVariables = new TextTemplatingVariables(); - var serviceProvider = new TextTemplatingServiceProvider(); var context = new TextTemplatingHostContext(project); + string applicationBase = GetAssemblyBaseLocation(); return new TextTemplatingHost(context, applicationBase); } diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHost.cs b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHost.cs index 7f40edde99..00f8e35d64 100644 --- a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHost.cs +++ b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHost.cs @@ -2,6 +2,7 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using System.Reflection; using Mono.TextTemplating; namespace ICSharpCode.TextTemplating @@ -24,6 +25,7 @@ namespace ICSharpCode.TextTemplating templatingAppDomain.Dispose(); templatingAppDomain = null; } + context.Dispose(); } public override AppDomain ProvideTemplatingAppDomain(string content) diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHostAppDomain.cs b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHostAppDomain.cs new file mode 100644 index 0000000000..13d2abe108 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHostAppDomain.cs @@ -0,0 +1,22 @@ +// 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; + +namespace ICSharpCode.TextTemplating +{ + public class TextTemplatingHostAppDomain : IAppDomain + { + AppDomain appDomain; + + public TextTemplatingHostAppDomain() + { + this.appDomain = AppDomain.CurrentDomain; + } + + public event ResolveEventHandler AssemblyResolve { + add { appDomain.AssemblyResolve += value; } + remove { appDomain.AssemblyResolve -= value; } + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHostAppDomainAssemblyResolver.cs b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHostAppDomainAssemblyResolver.cs new file mode 100644 index 0000000000..eb5939c9dd --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHostAppDomainAssemblyResolver.cs @@ -0,0 +1,73 @@ +// 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 System.Reflection; + +namespace ICSharpCode.TextTemplating +{ + public class TextTemplatingHostAppDomainAssemblyResolver : ITextTemplatingHostAppDomainAssemblyResolver + { + IAppDomain hostAppDomain; + IAddInTree addInTree; + + public TextTemplatingHostAppDomainAssemblyResolver() + : this( + new TextTemplatingHostAppDomain(), + new TextTemplatingAddInTree()) + { + } + + public TextTemplatingHostAppDomainAssemblyResolver( + IAppDomain hostAppDomain, + IAddInTree addInTree) + { + this.hostAppDomain = hostAppDomain; + this.addInTree = addInTree; + hostAppDomain.AssemblyResolve += ResolveAssembly; + } + + Assembly ResolveAssembly(object sender, ResolveEventArgs args) + { + var assemblyName = new AddInAssemblyName(args.Name); + return ResolveAssembly(assemblyName); + } + + Assembly ResolveAssembly(AddInAssemblyName assemblyName) + { + IAddIn addIn = FindAddIn(assemblyName); + if (addIn != null) { + return FindAddInAssemblyFromRuntimes(addIn); + } + return null; + } + + IAddIn FindAddIn(AddInAssemblyName assemblyName) + { + return addInTree + .GetAddIns() + .SingleOrDefault(addIn => assemblyName.Matches(addIn)); + } + + Assembly FindAddInAssemblyFromRuntimes(IAddIn addIn) + { + IAddInRuntime runtime = FindRuntime(addIn); + if (runtime != null) { + return runtime.LoadedAssembly; + } + return null; + } + + IAddInRuntime FindRuntime(IAddIn addIn) + { + var addinRuntime = new AddInAssemblyRuntime(addIn); + return addinRuntime.Runtime; + } + + public void Dispose() + { + hostAppDomain.AssemblyResolve -= ResolveAssembly; + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHostContext.cs b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHostContext.cs index eb1b5fd849..8d2bd88678 100644 --- a/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHostContext.cs +++ b/src/AddIns/Misc/TextTemplating/Project/Src/TextTemplatingHostContext.cs @@ -6,7 +6,7 @@ using ICSharpCode.SharpDevelop.Project; namespace ICSharpCode.TextTemplating { - public class TextTemplatingHostContext + public class TextTemplatingHostContext : IDisposable { ITextTemplatingAppDomainFactory appDomainFactory; ITextTemplatingAssemblyResolver assemblyResolver; @@ -51,7 +51,12 @@ namespace ICSharpCode.TextTemplating public string ResolveAssemblyReference(string assemblyReference) { - return assemblyResolver.Resolve(assemblyReference); + return assemblyResolver.ResolvePath(assemblyReference); + } + + public void Dispose() + { + assemblyResolver.Dispose(); } } } diff --git a/src/AddIns/Misc/TextTemplating/Project/TextTemplating.csproj b/src/AddIns/Misc/TextTemplating/Project/TextTemplating.csproj index 4bca22cf27..9c64b57848 100644 --- a/src/AddIns/Misc/TextTemplating/Project/TextTemplating.csproj +++ b/src/AddIns/Misc/TextTemplating/Project/TextTemplating.csproj @@ -50,25 +50,37 @@ Configuration\GlobalAssemblyInfo.cs + + + + + + + + + + + + @@ -81,6 +93,8 @@ + + diff --git a/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAddIn.cs b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAddIn.cs new file mode 100644 index 0000000000..60feff478c --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAddIn.cs @@ -0,0 +1,44 @@ +// 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.Collections.Generic; +using System.Reflection; +using ICSharpCode.TextTemplating; + +namespace TextTemplating.Tests.Helpers +{ + public class FakeAddIn : IAddIn + { + public FakeAddIn() + : this(String.Empty) + { + } + + public FakeAddIn(string id) + { + this.PrimaryIdentity = id; + } + + public string PrimaryIdentity { get; set; } + + public List FakeAddInRuntimes = new List(); + + public IEnumerable GetRuntimes() + { + return FakeAddInRuntimes; + } + + public FakeAddInRuntime AddFakeAddInRuntime(string assemblyFileName) + { + return AddFakeAddInRuntime(assemblyFileName, null); + } + + public FakeAddInRuntime AddFakeAddInRuntime(string assemblyFileName, Assembly loadedAssembly) + { + var runtime = new FakeAddInRuntime(assemblyFileName, loadedAssembly); + FakeAddInRuntimes.Add(runtime); + return runtime; + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAddInRuntime.cs b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAddInRuntime.cs new file mode 100644 index 0000000000..acf6027a83 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAddInRuntime.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 System.Reflection; +using ICSharpCode.TextTemplating; + +namespace TextTemplating.Tests.Helpers +{ + public class FakeAddInRuntime : IAddInRuntime + { + public FakeAddInRuntime(string assembly, Assembly loadedAssembly) + { + this.Assembly = assembly; + this.LoadedAssembly = loadedAssembly; + } + + public string Assembly { get; set; } + public Assembly LoadedAssembly { get; set; } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAddInTree.cs b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAddInTree.cs new file mode 100644 index 0000000000..39d45f1a35 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAddInTree.cs @@ -0,0 +1,28 @@ +// 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.Collections.Generic; +using System.Reflection; + +using ICSharpCode.TextTemplating; + +namespace TextTemplating.Tests.Helpers +{ + public class FakeAddInTree : IAddInTree + { + List FakeAddIns = new List(); + + public FakeAddIn AddFakeAddIn(string id) + { + var fakeAddIn = new FakeAddIn(id); + FakeAddIns.Add(fakeAddIn); + return fakeAddIn; + } + + public IEnumerable GetAddIns() + { + return FakeAddIns; + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAppDomain.cs b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAppDomain.cs new file mode 100644 index 0000000000..2e0f6376d5 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeAppDomain.cs @@ -0,0 +1,28 @@ +// 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.Reflection; +using ICSharpCode.TextTemplating; + +namespace TextTemplating.Tests.Helpers +{ + public class FakeAppDomain : IAppDomain + { + public event ResolveEventHandler AssemblyResolve; + + public Assembly FireAssemblyResolveEvent(string assemblyName) + { + var eventArgs = new ResolveEventArgs(assemblyName); + return FireAssemblyResolveEvent(eventArgs); + } + + public Assembly FireAssemblyResolveEvent(ResolveEventArgs e) + { + if (AssemblyResolve != null) { + return AssemblyResolve(this, e); + } + return null; + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeTextTemplatingAssemblyPathResolver.cs b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeTextTemplatingAssemblyPathResolver.cs new file mode 100644 index 0000000000..fa3018cc8e --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeTextTemplatingAssemblyPathResolver.cs @@ -0,0 +1,20 @@ +// 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.TextTemplating; + +namespace TextTemplating.Tests.Helpers +{ + public class FakeTextTemplatingAssemblyPathResolver : ITextTemplatingAssemblyPathResolver + { + public string AssemblyReferencePassedToResolvePath; + public string ResolvePathReturnValue; + + public string ResolvePath(string assemblyReference) + { + AssemblyReferencePassedToResolvePath = assemblyReference; + return ResolvePathReturnValue; + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeTextTemplatingAssemblyResolver.cs b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeTextTemplatingAssemblyResolver.cs index 33469cccf2..9a754ba711 100644 --- a/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeTextTemplatingAssemblyResolver.cs +++ b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeTextTemplatingAssemblyResolver.cs @@ -8,13 +8,20 @@ namespace TextTemplating.Tests.Helpers { public class FakeTextTemplatingAssemblyResolver : ITextTemplatingAssemblyResolver { - public string AssembyReferencePassedToResolve; - public string ResolveReturnValue = String.Empty; + public string AssembyReferencePassedToResolvePath; + public string ResolvePathReturnValue = String.Empty; - public string Resolve(string assemblyReference) + public string ResolvePath(string assemblyReference) { - this.AssembyReferencePassedToResolve = assemblyReference; - return ResolveReturnValue; + this.AssembyReferencePassedToResolvePath = assemblyReference; + return ResolvePathReturnValue; + } + + public bool IsDisposeCalled; + + public void Dispose() + { + IsDisposeCalled = true; } } } diff --git a/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeTextTemplatingHostAppDomainAssemblyResolver.cs b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeTextTemplatingHostAppDomainAssemblyResolver.cs new file mode 100644 index 0000000000..51ae68e3e0 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Test/Helpers/FakeTextTemplatingHostAppDomainAssemblyResolver.cs @@ -0,0 +1,18 @@ +// 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.TextTemplating; + +namespace TextTemplating.Tests.Helpers +{ + public class FakeTextTemplatingHostAppDomainAssemblyResolver : ITextTemplatingHostAppDomainAssemblyResolver + { + public bool IsDisposeCalled; + + public void Dispose() + { + IsDisposeCalled = true; + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Test/Helpers/TestableTextTemplatingHost.cs b/src/AddIns/Misc/TextTemplating/Test/Helpers/TestableTextTemplatingHost.cs index bf4cd0ada0..b016841ccf 100644 --- a/src/AddIns/Misc/TextTemplating/Test/Helpers/TestableTextTemplatingHost.cs +++ b/src/AddIns/Misc/TextTemplating/Test/Helpers/TestableTextTemplatingHost.cs @@ -16,8 +16,8 @@ namespace TextTemplating.Tests.Helpers public TestableTextTemplatingHost(string applicationBase) : this( - new FakeTextTemplatingAppDomainFactory(), - new FakeTextTemplatingAssemblyResolver(), + new FakeTextTemplatingAppDomainFactory(), + new FakeTextTemplatingAssemblyResolver(), new FakeTextTemplatingVariables(), new FakeServiceProvider(), applicationBase) @@ -31,7 +31,11 @@ namespace TextTemplating.Tests.Helpers FakeServiceProvider fakeServiceProvider, string applicationBase) : this( - new TextTemplatingHostContext(appDomainFactory, assemblyResolver, textTemplatingVariables, fakeServiceProvider), + new TextTemplatingHostContext( + appDomainFactory, + assemblyResolver, + textTemplatingVariables, + fakeServiceProvider), applicationBase) { FakeTextTemplatingAppDomainFactory = appDomainFactory; @@ -43,6 +47,7 @@ namespace TextTemplating.Tests.Helpers public TestableTextTemplatingHost(TextTemplatingHostContext context, string applicationBase) : base(context, applicationBase) { + HostContext = context; } public string CallResolveAssemblyReference(string assemblyReference) diff --git a/src/AddIns/Misc/TextTemplating/Test/Helpers/TextTemplatingHostContextTests.cs b/src/AddIns/Misc/TextTemplating/Test/Helpers/TextTemplatingHostContextTests.cs new file mode 100644 index 0000000000..ed5fcc939e --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Test/Helpers/TextTemplatingHostContextTests.cs @@ -0,0 +1,32 @@ +// 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.TextTemplating; +using NUnit.Framework; + +namespace TextTemplating.Tests.Helpers +{ + [TestFixture] + public class TextTemplatingHostContextTests + { + TextTemplatingHostContext hostContext; + FakeTextTemplatingAssemblyResolver fakeAssemblyResolver; + + void CreateHostContext() + { + var testableHost = new TestableTextTemplatingHost("Test"); + hostContext = testableHost.HostContext; + fakeAssemblyResolver = testableHost.FakeTextTemplatingAssemblyResolver; + } + + [Test] + public void Dispose_DisposeCalled_DisposesAssemblyResolver() + { + CreateHostContext(); + hostContext.Dispose(); + + Assert.IsTrue(fakeAssemblyResolver.IsDisposeCalled); + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Test/Src/AddInAssemblyNameTests.cs b/src/AddIns/Misc/TextTemplating/Test/Src/AddInAssemblyNameTests.cs new file mode 100644 index 0000000000..1c35bff85d --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Test/Src/AddInAssemblyNameTests.cs @@ -0,0 +1,81 @@ +// 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.TextTemplating; +using NUnit.Framework; +using TextTemplating.Tests.Helpers; + +namespace TextTemplating.Tests +{ + [TestFixture] + public class AddInAssemblyNameTests + { + AddInAssemblyName addInAssemblyName; + + void CreateAssemblyName(string assemblyName) + { + addInAssemblyName = new AddInAssemblyName(assemblyName); + } + + FakeAddIn CreateFakeAddIn(string id) + { + return new FakeAddIn(id); + } + + [Test] + public void Matches_AssemblyNameIsPackageManagementAndAddInIsICSharpCodePackageManagement_ReturnsTrue() + { + CreateAssemblyName("PackageManagement, Version=4.0, Culture=neutral, PublicKeyToken=null"); + FakeAddIn addIn = CreateFakeAddIn("ICSharpCode.PackageManagement"); + + bool matches = addInAssemblyName.Matches(addIn); + + Assert.IsTrue(matches); + } + + [Test] + public void Matches_AssemblyNameIsTestAndAddInIsICSharpCodePackageManagement_ReturnsFalse() + { + CreateAssemblyName("Test, Version=4.0, Culture=neutral, PublicKeyToken=null"); + FakeAddIn addIn = CreateFakeAddIn("ICSharpCode.PackageManagement"); + + bool matches = addInAssemblyName.Matches(addIn); + + Assert.IsFalse(matches); + } + + [Test] + public void Matches_AssemblyNameIsPackageManagementAndAddInIsICSharpCodePackageManagementInDifferentCase_ReturnsTrue() + { + CreateAssemblyName("PackageManagement, Version=4.0, Culture=neutral, PublicKeyToken=null"); + FakeAddIn addIn = CreateFakeAddIn("icsharpcode.packagemanagement"); + + bool matches = addInAssemblyName.Matches(addIn); + + Assert.IsTrue(matches); + } + + [Test] + public void Matches_NullAddInPrimaryIdentifier_ReturnsFalse() + { + CreateAssemblyName("Test, Version=1.0"); + FakeAddIn addIn = CreateFakeAddIn(null); + + bool matches = addInAssemblyName.Matches(addIn); + + Assert.IsFalse(matches); + } + + [Test] + public void Matches_NullAssemblyName_ReturnsFalse() + { + CreateAssemblyName(null); + FakeAddIn addIn = CreateFakeAddIn("Test"); + + bool matches = addInAssemblyName.Matches(addIn); + + Assert.IsFalse(matches); + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Test/Src/AddInAssemblyRuntimeTests.cs b/src/AddIns/Misc/TextTemplating/Test/Src/AddInAssemblyRuntimeTests.cs new file mode 100644 index 0000000000..845b52af06 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Test/Src/AddInAssemblyRuntimeTests.cs @@ -0,0 +1,130 @@ +// 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.TextTemplating; +using NUnit.Framework; +using TextTemplating.Tests.Helpers; + +namespace TextTemplating.Tests +{ + [TestFixture] + public class AddInAssemblyRuntimeTests + { + AddInAssemblyRuntime runtime; + + void CreateRuntime(string id) + { + var fakeAddIn = CreateFakeAddIn(id); + CreateRuntime(fakeAddIn); + } + + FakeAddIn CreateFakeAddIn(string id) + { + return new FakeAddIn(id); + } + + void CreateRuntime(FakeAddIn fakeAddIn) + { + runtime = new AddInAssemblyRuntime(fakeAddIn); + } + + [Test] + public void FileName_AddInIdIsICSharpCodePackageManagement_ReturnsPackageManagementDll() + { + CreateRuntime("ICSharpCode.PackageManagement"); + + string fileName = runtime.FileName; + + Assert.AreEqual("PackageManagement.dll", fileName); + } + + [Test] + public void FileName_AddInIdIsICSharpCodePackageManagementInLowerCase_ReturnsPackageManagementDll() + { + CreateRuntime("icsharpcode.packageManagement"); + + string fileName = runtime.FileName; + + Assert.AreEqual("packageManagement.dll", fileName); + } + + [Test] + public void FileName_AddInIdIsMyAddIn_ReturnsMyAddInDll() + { + CreateRuntime("MyAddIn"); + + string fileName = runtime.FileName; + + Assert.AreEqual("MyAddIn.dll", fileName); + } + + [Test] + public void Matches_FileNameMatchesAddInRuntimeFileName_ReturnsTrue() + { + CreateRuntime("ICSharpCode.PackageManagement"); + + bool match = runtime.Matches("PackageManagement.dll"); + + Assert.IsTrue(match); + } + + [Test] + public void Matches_FileNameDoesNotMatchAddInRuntimeFileName_ReturnsFalse() + { + CreateRuntime("ICSharpCode.PackageManagement"); + + bool match = runtime.Matches("test.dll"); + + Assert.IsFalse(match); + } + + [Test] + public void Matches_FileNameInDifferentCaseToAddInRuntimeFileName_ReturnsTrue() + { + CreateRuntime("ICSharpCode.PackageManagement"); + + bool match = runtime.Matches("packagemanagement.dll"); + + Assert.IsTrue(match); + } + + [Test] + public void Runtime_AddInHasMatchingAddInRuntime_ReturnsAddInRuntime() + { + FakeAddIn fakeAddIn = CreateFakeAddIn("ICSharpCode.PackageManagement"); + FakeAddInRuntime expectedRuntime = fakeAddIn.AddFakeAddInRuntime("PackageManagement.dll"); + CreateRuntime(fakeAddIn); + + IAddInRuntime addInRuntime = runtime.Runtime; + + Assert.AreEqual(expectedRuntime, addInRuntime); + } + + [Test] + public void Runtime_AddInHasThreeRuntimesWithSecondOneMatchingAddInRuntime_ReturnsSecondAddInRuntime() + { + FakeAddIn fakeAddIn = CreateFakeAddIn("ICSharpCode.PackageManagement"); + fakeAddIn.AddFakeAddInRuntime("Test.dll"); + FakeAddInRuntime expectedRuntime = fakeAddIn.AddFakeAddInRuntime("PackageManagement.dll"); + fakeAddIn.AddFakeAddInRuntime("AnotherTest.dll"); + CreateRuntime(fakeAddIn); + + IAddInRuntime addInRuntime = runtime.Runtime; + + Assert.AreEqual(expectedRuntime, addInRuntime); + } + + [Test] + public void Runtime_AddInHasMatchingAddInRuntimeButWthDifferentCase_ReturnsAddInRuntime() + { + FakeAddIn fakeAddIn = CreateFakeAddIn("ICSharpCode.PackageManagement"); + FakeAddInRuntime expectedRuntime = fakeAddIn.AddFakeAddInRuntime("packageManagement.dll"); + CreateRuntime(fakeAddIn); + + IAddInRuntime addInRuntime = runtime.Runtime; + + Assert.AreEqual(expectedRuntime, addInRuntime); + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingAssemblyPathResolverTests.cs b/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingAssemblyPathResolverTests.cs new file mode 100644 index 0000000000..21c1767938 --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingAssemblyPathResolverTests.cs @@ -0,0 +1,178 @@ +// 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.Internal.Templates; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.TextTemplating; +using NUnit.Framework; +using TextTemplating.Tests.Helpers; + +namespace TextTemplating.Tests +{ + [TestFixture] + public class TextTemplatingAssemblyPathResolverTests + { + TextTemplatingAssemblyPathResolver resolver; + IProject project; + FakeAssemblyParserService fakeAssemblyParserService; + FakeTextTemplatingPathResolver fakePathResolver; + + void CreateResolver() + { + project = ProjectHelper.CreateProject(); + fakeAssemblyParserService = new FakeAssemblyParserService(); + fakePathResolver = new FakeTextTemplatingPathResolver(); + resolver = new TextTemplatingAssemblyPathResolver(project, fakeAssemblyParserService, fakePathResolver); + } + + ReferenceProjectItem AddReferenceToProject(string referenceName) + { + ReferenceProjectItem projectItem = new ReferenceProjectItem(project, referenceName); + ProjectService.AddProjectItem(project, projectItem); + return projectItem; + } + + IProject GetProjectPassedToAssemblyParserService() + { + return ReferenceProjectItemPassedToGetReflectionProjectContentForReference.Project; + } + + ReferenceProjectItem ReferenceProjectItemPassedToGetReflectionProjectContentForReference { + get { return fakeAssemblyParserService.ItemPassedToGetReflectionProjectContentForReference; } + } + + ItemType GetReferenceItemTypePassedToAssemblyParserService() + { + return ReferenceProjectItemPassedToGetReflectionProjectContentForReference.ItemType; + } + + [Test] + public void ResolvePath_ProjectHasNoReferences_ReturnsAssemblyReferencePassedToMethod() + { + CreateResolver(); + fakeAssemblyParserService.FakeReflectionProjectContent = null; + string result = resolver.ResolvePath("Test"); + + Assert.AreEqual("Test", result); + } + + [Test] + public void ResolvePath_ProjectHasOneReferenceToTestAssemblyWithHintPathSet_ReturnsFullPathToTestAssembly() + { + CreateResolver(); + ReferenceProjectItem reference = AddReferenceToProject("test"); + string expectedFileName = @"d:\projects\MyProject\lib\Test.dll"; + reference.HintPath = expectedFileName; + + string result = resolver.ResolvePath("Test"); + + Assert.AreEqual(expectedFileName, result); + } + + [Test] + public void ResolvePath_AssemblyReferenceNameIsInDifferentCase_ReturnsFullPathToTestAssembly() + { + CreateResolver(); + ReferenceProjectItem reference = AddReferenceToProject("test"); + string expectedFileName = @"d:\projects\MyProject\lib\Test.dll"; + reference.HintPath = expectedFileName; + + string result = resolver.ResolvePath("TEST"); + + Assert.AreEqual(expectedFileName, result); + } + + [Test] + public void ResolvePath_ProjectHasOneReferenceToTestAssemblyWithFileNameSet_ReturnsFullPathToTestAssembly() + { + CreateResolver(); + ReferenceProjectItem reference = AddReferenceToProject("Test"); + string expectedFileName = @"d:\projects\MyProject\lib\Test.dll"; + reference.FileName = expectedFileName; + + string result = resolver.ResolvePath("Test"); + + Assert.AreEqual(expectedFileName, result); + } + + [Test] + public void ResolvePath_ProjectHasNoReferencesAndAssemblyReferenceInGac_ReturnsFullPathToAssemblyFoundFromAssemblyParserService() + { + CreateResolver(); + string expectedFileName = @"c:\Windows\System32\Gac\System.Data.dll"; + fakeAssemblyParserService.FakeReflectionProjectContent.AssemblyLocation = expectedFileName; + + string result = resolver.ResolvePath("System.Data"); + + Assert.AreEqual(expectedFileName, result); + } + + [Test] + public void ResolvePath_ProjectHasNoReferencesAndAssemblyReferenceInGac_ReferenceItemPassedToAssemblyParserServiceUsesProject() + { + CreateResolver(); + string result = resolver.ResolvePath("System.Data"); + IProject expectedProject = GetProjectPassedToAssemblyParserService(); + + Assert.AreEqual(project, expectedProject); + } + + [Test] + public void ResolvePath_ProjectHasNoReferencesAndAssemblyReferenceInGac_ReferenceItemPassedToAssemblyParserServiceIsReference() + { + CreateResolver(); + string result = resolver.ResolvePath("System.Data"); + ItemType type = GetReferenceItemTypePassedToAssemblyParserService(); + + Assert.AreEqual(ItemType.Reference, type); + } + + [Test] + public void ResolvePath_ProjectHasNoReferencesAndAssemblyReferenceInGac_ReferenceItemIncludePassedToAssemblyParserServiceIsAssemblyNameToResolvePath() + { + CreateResolver(); + string result = resolver.ResolvePath("System.Data"); + string referenceInclude = ReferenceProjectItemPassedToGetReflectionProjectContentForReference.Include; + + Assert.AreEqual("System.Data", referenceInclude); + } + + [Test] + public void ResolvePath_ProjectHasNoReferencesAndAssemblyReferenceNotFoundInGac_ReturnsAssemblyReferencePassedToMethod() + { + CreateResolver(); + fakeAssemblyParserService.FakeReflectionProjectContent = null; + + string result = resolver.ResolvePath("System.Data"); + + Assert.AreEqual("System.Data", result); + } + + [Test] + public void ResolvePath_AssemblyReferenceHasTemplateVariable_ReturnsExpandedAssemblyReferenceFileName() + { + CreateResolver(); + string path = @"$(SolutionDir)lib\Test.dll"; + string expectedPath = @"d:\projects\MyProject\lib\Test.dll"; + fakePathResolver.AddPath(path, expectedPath); + + string resolvedPath = resolver.ResolvePath(path); + + Assert.AreEqual(expectedPath, resolvedPath); + } + + [Test] + public void ResolvePath_AssemblyReferenceHasTemplateVariable_AssemblyParserServiceIsNotUsed() + { + CreateResolver(); + string path = @"$(SolutionDir)lib\Test.dll"; + string expectedPath = @"d:\projects\MyProject\lib\Test.dll"; + fakePathResolver.AddPath(path, expectedPath); + + string result = resolver.ResolvePath(path); + + Assert.IsFalse(fakeAssemblyParserService.IsGetReflectionProjectContentForReferenceCalled); + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingAssemblyResolverTests.cs b/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingAssemblyResolverTests.cs index 06d82167e3..8c332f1f97 100644 --- a/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingAssemblyResolverTests.cs +++ b/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingAssemblyResolverTests.cs @@ -14,165 +14,45 @@ namespace TextTemplating.Tests public class TextTemplatingAssemblyResolverTests { TextTemplatingAssemblyResolver resolver; - IProject project; - FakeAssemblyParserService fakeAssemblyParserService; - FakeTextTemplatingPathResolver fakePathResolver; + FakeTextTemplatingAssemblyPathResolver fakeAssemblyPathResolver; + FakeTextTemplatingHostAppDomainAssemblyResolver fakeHostAppDomainAssemblyResolver; void CreateResolver() { - project = ProjectHelper.CreateProject(); - fakeAssemblyParserService = new FakeAssemblyParserService(); - fakePathResolver = new FakeTextTemplatingPathResolver(); - resolver = new TextTemplatingAssemblyResolver(project, fakeAssemblyParserService, fakePathResolver); - } - - ReferenceProjectItem AddReferenceToProject(string referenceName) - { - ReferenceProjectItem projectItem = new ReferenceProjectItem(project, referenceName); - ProjectService.AddProjectItem(project, projectItem); - return projectItem; - } - - IProject GetProjectPassedToAssemblyParserService() - { - return ReferenceProjectItemPassedToGetReflectionProjectContentForReference.Project; - } - - ReferenceProjectItem ReferenceProjectItemPassedToGetReflectionProjectContentForReference { - get { return fakeAssemblyParserService.ItemPassedToGetReflectionProjectContentForReference; } - } - - ItemType GetReferenceItemTypePassedToAssemblyParserService() - { - return ReferenceProjectItemPassedToGetReflectionProjectContentForReference.ItemType; - } - - [Test] - public void Resolve_ProjectHasNoReferences_ReturnsAssemblyReferencePassedToMethod() - { - CreateResolver(); - fakeAssemblyParserService.FakeReflectionProjectContent = null; - string result = resolver.Resolve("Test"); - - Assert.AreEqual("Test", result); - } - - [Test] - public void Resolve_ProjectHasOneReferenceToTestAssemblyWithHintPathSet_ReturnsFullPathToTestAssembly() - { - CreateResolver(); - ReferenceProjectItem reference = AddReferenceToProject("test"); - string expectedFileName = @"d:\projects\MyProject\lib\Test.dll"; - reference.HintPath = expectedFileName; - - string result = resolver.Resolve("Test"); - - Assert.AreEqual(expectedFileName, result); - } - - [Test] - public void Resolve_AssemblyReferenceNameIsInDifferentCase_ReturnsFullPathToTestAssembly() - { - CreateResolver(); - ReferenceProjectItem reference = AddReferenceToProject("test"); - string expectedFileName = @"d:\projects\MyProject\lib\Test.dll"; - reference.HintPath = expectedFileName; - - string result = resolver.Resolve("TEST"); - - Assert.AreEqual(expectedFileName, result); - } - - [Test] - public void Resolve_ProjectHasOneReferenceToTestAssemblyWithFileNameSet_ReturnsFullPathToTestAssembly() - { - CreateResolver(); - ReferenceProjectItem reference = AddReferenceToProject("Test"); - string expectedFileName = @"d:\projects\MyProject\lib\Test.dll"; - reference.FileName = expectedFileName; - - string result = resolver.Resolve("Test"); - - Assert.AreEqual(expectedFileName, result); + fakeAssemblyPathResolver = new FakeTextTemplatingAssemblyPathResolver(); + fakeHostAppDomainAssemblyResolver = new FakeTextTemplatingHostAppDomainAssemblyResolver(); + resolver = new TextTemplatingAssemblyResolver( + fakeAssemblyPathResolver, + fakeHostAppDomainAssemblyResolver); } [Test] - public void Resolve_ProjectHasNoReferencesAndAssemblyReferenceInGac_ReturnsFullPathToAssemblyFoundFromAssemblyParserService() + public void ResolvePath_PathPassed_PathPassedToAssemblyPathResolver() { CreateResolver(); - string expectedFileName = @"c:\Windows\System32\Gac\System.Data.dll"; - fakeAssemblyParserService.FakeReflectionProjectContent.AssemblyLocation = expectedFileName; + resolver.ResolvePath("Test"); - string result = resolver.Resolve("System.Data"); - - Assert.AreEqual(expectedFileName, result); + Assert.AreEqual("Test", fakeAssemblyPathResolver.AssemblyReferencePassedToResolvePath); } [Test] - public void Resolve_ProjectHasNoReferencesAndAssemblyReferenceInGac_ReferenceItemPassedToAssemblyParserServiceUsesProject() + public void ResolvePath_PathPassed_ReturnAssemblyPathFromAssemblyPathResolver() { CreateResolver(); - string result = resolver.Resolve("System.Data"); - IProject expectedProject = GetProjectPassedToAssemblyParserService(); + string expectedPath = @"d:\test\MyAssembly.dll"; + fakeAssemblyPathResolver.ResolvePathReturnValue = expectedPath; + string path = resolver.ResolvePath("Test"); - Assert.AreEqual(project, expectedProject); + Assert.AreEqual(expectedPath, path); } [Test] - public void Resolve_ProjectHasNoReferencesAndAssemblyReferenceInGac_ReferenceItemPassedToAssemblyParserServiceIsReference() + public void Dispose_DisposeCalled_DisposesHostAppDomainAssemblyResolver() { CreateResolver(); - string result = resolver.Resolve("System.Data"); - ItemType type = GetReferenceItemTypePassedToAssemblyParserService(); - - Assert.AreEqual(ItemType.Reference, type); - } - - [Test] - public void Resolve_ProjectHasNoReferencesAndAssemblyReferenceInGac_ReferenceItemIncludePassedToAssemblyParserServiceIsAssemblyNameToResolve() - { - CreateResolver(); - string result = resolver.Resolve("System.Data"); - string referenceInclude = ReferenceProjectItemPassedToGetReflectionProjectContentForReference.Include; - - Assert.AreEqual("System.Data", referenceInclude); - } - - [Test] - public void Resolve_ProjectHasNoReferencesAndAssemblyReferenceNotFoundInGac_ReturnsAssemblyReferencePassedToMethod() - { - CreateResolver(); - fakeAssemblyParserService.FakeReflectionProjectContent = null; - - string result = resolver.Resolve("System.Data"); - - Assert.AreEqual("System.Data", result); - } - - [Test] - public void Resolve_AssemblyReferenceHasTemplateVariable_ReturnsExpandedAssemblyReferenceFileName() - { - CreateResolver(); - string path = @"$(SolutionDir)lib\Test.dll"; - string expectedPath = @"d:\projects\MyProject\lib\Test.dll"; - fakePathResolver.AddPath(path, expectedPath); - - string resolvedPath = resolver.Resolve(path); - - Assert.AreEqual(expectedPath, resolvedPath); - } - - [Test] - public void Resolve_AssemblyReferenceHasTemplateVariable_AssemblyParserServiceIsNotUsed() - { - CreateResolver(); - string path = @"$(SolutionDir)lib\Test.dll"; - string expectedPath = @"d:\projects\MyProject\lib\Test.dll"; - fakePathResolver.AddPath(path, expectedPath); - - string result = resolver.Resolve(path); + resolver.Dispose(); - Assert.IsFalse(fakeAssemblyParserService.IsGetReflectionProjectContentForReferenceCalled); + Assert.IsTrue(fakeHostAppDomainAssemblyResolver.IsDisposeCalled); } } } diff --git a/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingHostAppDomainAssemblyResolverTests.cs b/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingHostAppDomainAssemblyResolverTests.cs new file mode 100644 index 0000000000..f0eb4c6bea --- /dev/null +++ b/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingHostAppDomainAssemblyResolverTests.cs @@ -0,0 +1,144 @@ +// 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.Reflection; +using ICSharpCode.TextTemplating; +using NUnit.Framework; +using TextTemplating.Tests.Helpers; + +namespace TextTemplating.Tests +{ + [TestFixture] + public class TextTemplatingHostAppDomainAssemblyResolverTests + { + TextTemplatingHostAppDomainAssemblyResolver resolver; + FakeAppDomain fakeAppDomain; + FakeAddInTree fakeAddInTree; + + void CreateResolver() + { + fakeAppDomain = new FakeAppDomain(); + fakeAddInTree = new FakeAddInTree(); + resolver = new TextTemplatingHostAppDomainAssemblyResolver(fakeAppDomain, fakeAddInTree); + } + + FakeAddIn AddFakeAddInToTree(string id) + { + return fakeAddInTree.AddFakeAddIn(id); + } + + void AddFakeRuntime(FakeAddIn fakeAddIn, string runtimeFileName) + { + AddFakeRuntime(fakeAddIn, runtimeFileName, null); + } + + void AddFakeRuntime(FakeAddIn fakeAddIn, string runtimeFileName, Assembly assembly) + { + fakeAddIn.AddFakeAddInRuntime(runtimeFileName, assembly); + } + + [Test] + public void AssemblyResolve_EventFiredForAssemblyThatMatchesAddInAssembly_ReturnsAddInAssembly() + { + CreateResolver(); + FakeAddIn fakeAddIn = AddFakeAddInToTree("ICSharpCode.PackageManagement"); + Assembly expectedAssembly = typeof(string).Assembly; + AddFakeRuntime(fakeAddIn, "PackageManagement.dll", expectedAssembly); + + string assemblyName = "PackageManagement, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"; + Assembly assembly = fakeAppDomain.FireAssemblyResolveEvent(assemblyName); + + Assert.AreEqual(expectedAssembly, assembly); + } + + + + [Test] + public void Dispose_EventFiredForAssemblyThatMatchesAddInAssemblyAfter_DoesNotReturnAddInAssembly() + { + CreateResolver(); + FakeAddIn fakeAddIn = AddFakeAddInToTree("ICSharpCode.PackageManagement"); + Assembly expectedAssembly = typeof(string).Assembly; + AddFakeRuntime(fakeAddIn, "PackageManagement.dll", expectedAssembly); + + resolver.Dispose(); + + string assemblyName = "PackageManagement, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"; + Assembly assembly = fakeAppDomain.FireAssemblyResolveEvent(assemblyName); + + Assert.IsNull(assembly); + } + + [Test] + public void AssemblyResolve_EventFiredForAssemblyThatMatchesSecondAddInAssembly_ReturnsSecondAddInAssembly() + { + CreateResolver(); + AddFakeAddInToTree("ICSharpCode.Test"); + FakeAddIn fakeAddIn = AddFakeAddInToTree("ICSharpCode.PackageManagement"); + Assembly expectedAssembly = this.GetType().Assembly; + AddFakeRuntime(fakeAddIn, "PackageManagement.dll", expectedAssembly); + + string assemblyName = "PackageManagement, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"; + Assembly assembly = fakeAppDomain.FireAssemblyResolveEvent(assemblyName); + + Assert.AreEqual(expectedAssembly, assembly); + } + + [Test] + public void AssemblyResolve_EventFiredForAssemblyThatMatchesFirstOutOfTwoAddInAssemblies_ReturnsFirstAddInAssembly() + { + CreateResolver(); + FakeAddIn fakeAddIn = AddFakeAddInToTree("ICSharpCode.PackageManagement"); + Assembly expectedAssembly = this.GetType().Assembly; + AddFakeRuntime(fakeAddIn, "PackageManagement.dll", expectedAssembly); + + AddFakeAddInToTree("ICSharpCode.Test"); + + string assemblyName = "PackageManagement, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"; + Assembly assembly = fakeAppDomain.FireAssemblyResolveEvent(assemblyName); + + Assert.AreEqual(expectedAssembly, assembly); + } + + [Test] + public void AssemblyResolve_EventFiredForAssemblyThatDoesNotMatchAnyAddIns_ReturnsNull() + { + CreateResolver(); + AddFakeAddInToTree("ICSharpCode.Test"); + + string assemblyName = "Unknown, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"; + Assembly assembly = fakeAppDomain.FireAssemblyResolveEvent(assemblyName); + + Assert.IsNull(assembly); + } + + [Test] + public void AssemblyResolve_MatchedAddInHasNoRuntimes_ReturnsNull() + { + CreateResolver(); + AddFakeAddInToTree("ICSharpCode.Test"); + + string assemblyName = "Test, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"; + Assembly assembly = fakeAppDomain.FireAssemblyResolveEvent(assemblyName); + + Assert.IsNull(assembly); + } + + [Test] + public void AssemblyResolve_AddInAssemblyIsSecondOfThreeRuntimes_ReturnsAddInAssemblyFromSecondRuntime() + { + CreateResolver(); + FakeAddIn fakeAddIn = AddFakeAddInToTree("ICSharpCode.PackageManagement"); + AddFakeRuntime(fakeAddIn, ":ICSharpCode.SharpDevelop"); + Assembly expectedAssembly = this.GetType().Assembly; + AddFakeRuntime(fakeAddIn, "PackageManagement.dll", expectedAssembly); + AddFakeRuntime(fakeAddIn, "IronPython.dll"); + + string assemblyName = "PackageManagement, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"; + Assembly assembly = fakeAppDomain.FireAssemblyResolveEvent(assemblyName); + + Assert.AreEqual(expectedAssembly, assembly); + } + } +} diff --git a/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingHostTests.cs b/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingHostTests.cs index 681ba9b1ed..2a524f3a38 100644 --- a/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingHostTests.cs +++ b/src/AddIns/Misc/TextTemplating/Test/Src/TextTemplatingHostTests.cs @@ -18,6 +18,7 @@ namespace TextTemplating.Tests FakeTextTemplatingAssemblyResolver fakeAssemblyResolver; FakeTextTemplatingVariables fakeTextTemplatingVariables; FakeServiceProvider fakeServiceProvider; + TextTemplatingHostContext hostContext; void CreateHost() { @@ -32,6 +33,7 @@ namespace TextTemplating.Tests fakeAssemblyResolver = host.FakeTextTemplatingAssemblyResolver; fakeTextTemplatingVariables = host.FakeTextTemplatingVariables; fakeServiceProvider = host.FakeServiceProvider; + hostContext = host.HostContext; } void AddTemplateVariableValue(string variableName, string variableValue) @@ -108,14 +110,14 @@ namespace TextTemplating.Tests CreateHost(); host.CallResolveAssemblyReference("MyReference"); - Assert.AreEqual("MyReference", fakeAssemblyResolver.AssembyReferencePassedToResolve); + Assert.AreEqual("MyReference", fakeAssemblyResolver.AssembyReferencePassedToResolvePath); } [Test] public void ResolveAssemblyReference_PassedMyAssemblyReference_ReturnsFileNameReturnedFromAssemblyResolverResolveMethod() { CreateHost(); - fakeAssemblyResolver.ResolveReturnValue = @"d:\projects\references\MyReference.dll"; + fakeAssemblyResolver.ResolvePathReturnValue = @"d:\projects\references\MyReference.dll"; string result = host.CallResolveAssemblyReference("MyReference"); Assert.AreEqual(@"d:\projects\references\MyReference.dll", result); @@ -143,5 +145,15 @@ namespace TextTemplating.Tests Assert.AreEqual(expectedService, service); } + + [Test] + public void Dispose_DisposeCalledAfterProvideTemplatingAppDomainCalled_DisposesAssemblyResolver() + { + CreateHost(); + host.ProvideTemplatingAppDomain("test"); + host.Dispose(); + + Assert.IsTrue(fakeAssemblyResolver.IsDisposeCalled); + } } } diff --git a/src/AddIns/Misc/TextTemplating/Test/TextTemplating.Tests.csproj b/src/AddIns/Misc/TextTemplating/Test/TextTemplating.Tests.csproj index bddd0bf396..b40385c449 100644 --- a/src/AddIns/Misc/TextTemplating/Test/TextTemplating.Tests.csproj +++ b/src/AddIns/Misc/TextTemplating/Test/TextTemplating.Tests.csproj @@ -55,17 +55,23 @@ Configuration\GlobalAssemblyInfo.cs + + + + + + @@ -75,12 +81,17 @@ + + + + +