Browse Source

Use new ProjectTemplate base class.

We now allow loading .xpt files from embedded resources.
pull/32/merge
Daniel Grunwald 12 years ago
parent
commit
e0d6d8d9d9
  1. 2
      src/AddIns/BackendBindings/CppBinding/CppBinding/CppBinding.addin
  2. 36
      src/AddIns/BackendBindings/CppBinding/CppBinding/CppBinding.csproj
  3. 3
      src/AddIns/BackendBindings/FSharpBinding/FSharpBinding.addin
  4. 12
      src/AddIns/BackendBindings/FSharpBinding/FSharpBinding.csproj
  5. 2
      src/AddIns/BackendBindings/WixBinding/Project/WixBinding.addin
  6. 7
      src/AddIns/DisplayBindings/Data/ICSharpCode.Data.Addin/ICSharpCode.Data.Addin.csproj
  7. 2
      src/AddIns/DisplayBindings/Data/ICSharpCode.Data.Addin/ICSharpCode.Data.addin
  8. 0
      src/AddIns/DisplayBindings/Data/ICSharpCode.Data.Addin/Templates/CSharp.EDMX.xft
  9. 2
      src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsEditor.addin
  10. 6
      src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsEditor.csproj
  11. 5
      src/AddIns/Misc/PackageManagement/Project/Src/InstallProjectTemplatePackagesCommand.cs
  12. 7
      src/AddIns/Misc/PackageManagement/Test/Src/InstallProjectTemplatePackagesCommandTests.cs
  13. 2
      src/AddIns/Misc/TextTemplating/Project/TextTemplating.addin
  14. 5
      src/Main/Base/Project/ICSharpCode.SharpDevelop.addin
  15. 2
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  16. 10
      src/Main/Base/Project/Services/IFileSystem.cs
  17. 84
      src/Main/Base/Project/Src/Gui/Dialogs/NewProjectDialog.cs
  18. 19
      src/Main/Base/Project/Src/Internal/Templates/File/FileDescriptionTemplate.cs
  19. 42
      src/Main/Base/Project/Src/Internal/Templates/File/FileTemplate.cs
  20. 43
      src/Main/Base/Project/Src/Internal/Templates/Project/ProjectDescriptor.cs
  21. 185
      src/Main/Base/Project/Src/Internal/Templates/Project/ProjectTemplate.cs
  22. 47
      src/Main/Base/Project/Src/Internal/Templates/Project/SolutionDescriptor.cs
  23. 15
      src/Main/Base/Project/Src/Internal/Templates/TemplateCategorySortOrderFile.cs
  24. 3
      src/Main/Base/Project/Templates/FileTemplateResult.cs
  25. 10
      src/Main/Base/Project/Templates/ITemplateService.cs
  26. 44
      src/Main/Base/Project/Templates/ProjectTemplate.cs
  27. 21
      src/Main/Base/Project/Templates/ProjectTemplateOptions.cs
  28. 17
      src/Main/Base/Project/Templates/ProjectTemplateResult.cs
  29. 83
      src/Main/Base/Project/Util/EmbeddedResourceFileSystem.cs
  30. 18
      src/Main/Base/Project/Util/IImage.cs
  31. 1
      src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj
  32. 63
      src/Main/Base/Test/ReadOnlyDocumentTests.cs
  33. 37
      src/Main/Core/Project/Src/Services/FileUtility/FileUtility.Minimal.cs
  34. 27
      src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs
  35. 5
      src/Main/Core/Project/Src/Services/FileUtility/PathName.cs
  36. 22
      src/Main/Core/Test/FileNameTests.cs
  37. 29
      src/Main/Core/Test/FileUtilityTests.cs
  38. 3
      src/Main/Core/Test/ICSharpCode.Core.Tests.csproj
  39. 2
      src/Main/SharpDevelop/Services/UIService.cs
  40. 1
      src/Main/SharpDevelop/SharpDevelop.csproj
  41. 77
      src/Main/SharpDevelop/Templates/TemplateFileDoozer.cs
  42. 22
      src/Main/SharpDevelop/Templates/TemplateService.cs
  43. 26
      src/Setup/Files.wxs
  44. 4
      src/Setup/Setup.wxs

2
src/AddIns/BackendBindings/CppBinding/CppBinding/CppBinding.addin

@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
</Path>
<Path name = "/SharpDevelop/BackendBindings/Templates">
<Directory id = "C++" path = "./Templates" />
<TemplateFile id = "C++" resourceNamespace = "ICSharpCode.CppBinding.Templates" />
</Path>
<Path name = "/SharpDevelop/BackendBindings/TemplateCommands">

36
src/AddIns/BackendBindings/CppBinding/CppBinding/CppBinding.csproj

@ -98,26 +98,26 @@ @@ -98,26 +98,26 @@
</None>
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="CppProjectBinding.cs" />
<None Include="Templates\ConsoleProject.xpt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Templates\Empty.xft">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Templates\EmptyClass.xft">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Templates\Library.xpt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Templates\UnmanagedConsoleProject.xpt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<EmbeddedResource Include="Templates\ConsoleProject.xpt">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="Templates\Empty.xft">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="Templates\EmptyClass.xft">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="Templates\Library.xpt">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="Templates\UnmanagedConsoleProject.xpt">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Content Include="Templates\DefaultAssemblyInfo.cpp">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="Templates\DefaultAssemblyInfo.cpp">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">

3
src/AddIns/BackendBindings/FSharpBinding/FSharpBinding.addin

@ -12,7 +12,6 @@ @@ -12,7 +12,6 @@
<Runtime>
<Import assembly = "FSharpBinding.dll"/>
<Import assembly = ":ICSharpCode.SharpDevelop"/>
<Import assembly = ":ICSharpCode.SharpDevelop.Dom"/>
<Import assembly = "$ICSharpCode.CSharpBinding/CSharpBinding.dll"/>
</Runtime>
@ -29,7 +28,7 @@ @@ -29,7 +28,7 @@
</Path>
<Path name = "/SharpDevelop/BackendBindings/Templates">
<Directory id = "fsc" path = "./Templates" />
<TemplateFile id = "fsc" resourceNamespace = "FSharpBinding.Templates" />
</Path>
<Path name = "/SharpDevelop/Workbench/FileFilter">

12
src/AddIns/BackendBindings/FSharpBinding/FSharpBinding.csproj

@ -70,12 +70,12 @@ @@ -70,12 +70,12 @@
<None Include="FSharpBinding.addin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Templates\ConsoleProject.xpt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="Templates\EmptyClass.xft">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<EmbeddedResource Include="Templates\ConsoleProject.xpt">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="Templates\EmptyClass.xft">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">

2
src/AddIns/BackendBindings/WixBinding/Project/WixBinding.addin

@ -39,7 +39,7 @@ @@ -39,7 +39,7 @@
<!-- WiX project and file templates -->
<Path name = "/SharpDevelop/BackendBindings/Templates">
<Directory id = "WiX" path = "./Templates" />
<TemplateFile id = "WiX" path = "./Templates" />
</Path>
<Path name = "/AddIns/FileTypeRegisterer/FileTypes">

7
src/AddIns/DisplayBindings/Data/ICSharpCode.Data.Addin/ICSharpCode.Data.Addin.csproj

@ -91,9 +91,9 @@ @@ -91,9 +91,9 @@
<Compile Include="Pad\DatabasesTreeViewUserControl.xaml.cs">
<DependentUpon>DatabasesTreeViewUserControl.xaml</DependentUpon>
</Compile>
<None Include="Templates\Files\CSharp.EDMX.xft">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<EmbeddedResource Include="Templates\CSharp.EDMX.xft">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Page Include="Pad\DatabasesTreeViewUserControl.xaml">
@ -112,7 +112,6 @@ @@ -112,7 +112,6 @@
</PropertyGroup>
<ItemGroup>
<Folder Include="Templates" />
<Folder Include="Templates\Files" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">

2
src/AddIns/DisplayBindings/Data/ICSharpCode.Data.Addin/ICSharpCode.Data.addin

@ -44,7 +44,7 @@ @@ -44,7 +44,7 @@
<!--Template path -->
<Path name = "/SharpDevelop/BackendBindings/Templates">
<Directory id = "Data" path = "./Templates/Files" />
<TemplateFile id = "Data" resourceNamespace = "ICSharpCode.Data.Addin.Templates" />
</Path>
<!-- Custom tools path-->

0
src/AddIns/DisplayBindings/Data/ICSharpCode.Data.Addin/Templates/Files/CSharp.EDMX.xft → src/AddIns/DisplayBindings/Data/ICSharpCode.Data.Addin/Templates/CSharp.EDMX.xft

2
src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsEditor.addin

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
</Runtime>
<Path name = "/SharpDevelop/BackendBindings/Templates">
<Directory id = "settings" path = "." />
<TemplateFile id = "settings" resourceNamespace = "ICSharpCode.SettingsEditor" />
</Path>
<Path name = "/SharpDevelop/Workbench/FileFilter">

6
src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsEditor.csproj

@ -57,9 +57,9 @@ @@ -57,9 +57,9 @@
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<None Include="EmptySettingsFile.xft">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<EmbeddedResource Include="EmptySettingsFile.xft">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
<None Include="SettingsEditor.addin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>

5
src/AddIns/Misc/PackageManagement/Project/Src/InstallProjectTemplatePackagesCommand.cs

@ -8,6 +8,7 @@ using ICSharpCode.Core; @@ -8,6 +8,7 @@ using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Internal.Templates;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Templates;
namespace ICSharpCode.PackageManagement
{
@ -65,8 +66,8 @@ namespace ICSharpCode.PackageManagement @@ -65,8 +66,8 @@ namespace ICSharpCode.PackageManagement
IEnumerable<MSBuildBasedProject> GetCreatedProjects()
{
var createInfo = Owner as ProjectCreateOptions;
return createInfo != null ? createInfo.CreatedProjects.OfType<MSBuildBasedProject>() : Enumerable.Empty<MSBuildBasedProject>();
var createInfo = Owner as ProjectTemplateResult;
return createInfo != null ? createInfo.NewProjects.OfType<MSBuildBasedProject>() : Enumerable.Empty<MSBuildBasedProject>();
}
IPackageReferencesForProject CreatePackageReferencesForProject(MSBuildBasedProject project)

7
src/AddIns/Misc/PackageManagement/Test/Src/InstallProjectTemplatePackagesCommandTests.cs

@ -9,6 +9,7 @@ using ICSharpCode.SharpDevelop; @@ -9,6 +9,7 @@ using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Internal.Templates;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Templates;
using NUnit.Framework;
using PackageManagement.Tests.Helpers;
@ -38,15 +39,15 @@ namespace PackageManagement.Tests @@ -38,15 +39,15 @@ namespace PackageManagement.Tests
void RunCommandWithProjectCreateInfoAsOwner(List<TestableProject> projects)
{
var createInfo = new ProjectCreateOptions();
createInfo.CreatedProjects.AddRange(projects);
var createInfo = new ProjectTemplateResult(new ProjectTemplateOptions());
createInfo.NewProjects.AddRange(projects);
command.FakeProjectService.ProjectCollections.Add(new ImmutableModelCollection<IProject>(projects));
RunCommandWithProjectCreateInfoAsOwner(createInfo);
}
void RunCommandWithProjectCreateInfoAsOwner(ProjectCreateOptions createInfo)
void RunCommandWithProjectCreateInfoAsOwner(ProjectTemplateResult createInfo)
{
((ICommand)command).Execute(createInfo);
}

2
src/AddIns/Misc/TextTemplating/Project/TextTemplating.addin

@ -49,7 +49,7 @@ @@ -49,7 +49,7 @@
</Path>
<Path name="/SharpDevelop/BackendBindings/Templates">
<Directory id="TextTemplating" path="./Templates"/>
<TemplateFile id="TextTemplating" path="./Templates"/>
</Path>
<!-- Defines service providers that will be used by the text templating host

5
src/Main/Base/Project/ICSharpCode.SharpDevelop.addin

@ -47,6 +47,7 @@ @@ -47,6 +47,7 @@
<Doozer name="Directory" class="ICSharpCode.SharpDevelop.DirectoryDoozer"/>
<Doozer name="TaskBoundAdditionalLogger" class="ICSharpCode.SharpDevelop.Project.TaskBoundAdditionalLoggerDoozer"/>
<Doozer name="TaskBoundLoggerFilter" class="ICSharpCode.SharpDevelop.Project.TaskBoundLoggerFilterDoozer"/>
<Doozer name="TemplateFile" class="ICSharpCode.SharpDevelop.Templates.TemplateFileDoozer"/>
</Import>
<Import assembly=":SharpDevelop">
<Doozer name="Parser" class="ICSharpCode.SharpDevelop.Parser.ParserDoozer"/>
@ -2325,6 +2326,10 @@ @@ -2325,6 +2326,10 @@
class = "ICSharpCode.SharpDevelop.Gui.ToggleConsoleWordWrapCommand"/>
</Path>
<Path name = "/SharpDevelop/BackendBindings/Templates">
<TemplateFile path="../data/templates" />
</Path>
<Path name = "/SharpDevelop/BackendBindings/TemplateCommands">
<Class id="CheckPortableLibraryInstalled"
class="ICSharpCode.SharpDevelop.Project.PortableLibrary.CheckPortableLibraryInstalled"/>

2
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -240,6 +240,7 @@ @@ -240,6 +240,7 @@
<Compile Include="Templates\FileTemplateResult.cs" />
<Compile Include="Templates\ITemplateService.cs" />
<Compile Include="Templates\ProjectTemplate.cs" />
<Compile Include="Templates\ProjectTemplateOptions.cs" />
<Compile Include="Templates\ProjectTemplateResult.cs" />
<Compile Include="Templates\TemplateBase.cs" />
<Compile Include="Templates\TemplateLoadException.cs" />
@ -251,6 +252,7 @@ @@ -251,6 +252,7 @@
<Compile Include="Util\DebugTimer.cs" />
<Compile Include="Util\DotnetDetection.cs" />
<Compile Include="Util\EasyCodeDom.cs" />
<Compile Include="Util\EmbeddedResourceFileSystem.cs" />
<Compile Include="Util\EnumBinding.cs" />
<Compile Include="Util\EventAdapter.cs" />
<Compile Include="Util\FakeMessageLoop.cs" />

10
src/Main/Base/Project/Services/IFileSystem.cs

@ -46,6 +46,16 @@ namespace ICSharpCode.SharpDevelop @@ -46,6 +46,16 @@ namespace ICSharpCode.SharpDevelop
IEnumerable<FileName> GetFiles(DirectoryName directory, string searchPattern = "*", SearchOption searchOption = SearchOption.TopDirectoryOnly);
}
public static class FileSystemExtensions
{
public static string ReadAllText(this IReadOnlyFileSystem fileSystem, FileName fileName)
{
using (var reader = fileSystem.OpenText(fileName)) {
return reader.ReadToEnd();
}
}
}
sealed class EmptyFileSystem : IFileSystem
{
void IFileSystem.Delete(FileName path)

84
src/Main/Base/Project/Src/Gui/Dialogs/NewProjectDialog.cs

@ -5,8 +5,8 @@ using System; @@ -5,8 +5,8 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Internal.Templates;
@ -16,13 +16,16 @@ using Microsoft.Build.Exceptions; @@ -16,13 +16,16 @@ using Microsoft.Build.Exceptions;
namespace ICSharpCode.SharpDevelop.Project.Dialogs
{
using ICSharpCode.SharpDevelop.Templates;
internal partial class NewProjectDialog : Form
{
protected List<TemplateItem> alltemplates = new List<TemplateItem>();
protected List<Category> categories = new List<Category>();
internal ProjectTemplateResult result;
// icon resource name => image index
protected Dictionary<string, int> icons = new Dictionary<string, int>();
protected Dictionary<IImage, int> icons = new Dictionary<IImage, int>();
protected bool createNewSolution;
@ -33,7 +36,6 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs @@ -33,7 +36,6 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs
public NewProjectDialog(bool createNewSolution)
{
StandardHeader.SetHeaders();
this.createNewSolution = createNewSolution;
MyInitializeComponents();
@ -59,21 +61,19 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs @@ -59,21 +61,19 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs
// load the icons and set their index from the image list in the hashtable
int i = 0;
Dictionary<string, int> tmp = new Dictionary<string, int>(icons);
foreach (KeyValuePair<string, int> entry in icons) {
Bitmap bitmap = IconService.GetBitmap(entry.Key);
foreach (IImage icon in icons.Keys.ToArray()) {
Bitmap bitmap = icon.Bitmap;
if (bitmap != null) {
smalllist.Images.Add(bitmap);
imglist.Images.Add(bitmap);
tmp[entry.Key] = ++i;
icons[icon] = ++i;
} else {
LoggingService.Warn("NewProjectDialog: can't load bitmap " + entry.Key.ToString() + " using default");
LoggingService.Warn("NewProjectDialog: can't load bitmap " + icon + " using default");
}
}
// set the correct imageindex for all templates
icons = tmp;
foreach (TemplateItem item in alltemplates) {
if (item.Template.Icon == null) {
item.ImageIndex = 0;
@ -137,8 +137,8 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs @@ -137,8 +137,8 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs
protected virtual void InitializeTemplates()
{
foreach (ProjectTemplate template in ProjectTemplate.ProjectTemplates) {
if (template.ProjectDescriptor == null && createNewSolution == false) {
foreach (ProjectTemplate template in SD.Templates.ProjectTemplates) {
if (!template.IsVisible(SolutionFolder != null ? SolutionFolder.ParentSolution : null)) {
// Do not show solution template when added a new project to existing solution
continue;
}
@ -146,12 +146,10 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs @@ -146,12 +146,10 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs
if (titem.Template.Icon != null) {
icons[titem.Template.Icon] = 0; // "create template icon"
}
if (template.NewProjectDialogVisible == true) {
Category cat = GetCategory(StringParser.Parse(titem.Template.Category), StringParser.Parse(titem.Template.Subcategory));
cat.Templates.Add(titem);
if (cat.Templates.Count == 1)
titem.Selected = true;
}
Category cat = GetCategory(StringParser.Parse(titem.Template.Category), StringParser.Parse(titem.Template.Subcategory));
cat.Templates.Add(titem);
if (cat.Templates.Count == 1)
titem.Selected = true;
alltemplates.Add(titem);
}
}
@ -161,16 +159,13 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs @@ -161,16 +159,13 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs
targetFrameworkComboBox.SelectedIndexChanged -= TargetFrameworkComboBoxSelectedIndexChanged;
targetFrameworkComboBox.Items.Clear();
if (categoryTreeView.SelectedNode != null) {
foreach (TargetFramework fx in TargetFramework.TargetFrameworks) {
if (fx.DisplayName == null || !fx.IsAvailable())
continue;
foreach (TemplateItem item in ((Category)categoryTreeView.SelectedNode).Templates) {
if (item.Template.HasSupportedTargetFrameworks && item.Template.SupportsTargetFramework(fx)) {
targetFrameworkComboBox.Items.Add(fx);
break;
}
}
HashSet<TargetFramework> availableTargetFrameworks = new HashSet<TargetFramework>();
foreach (TemplateItem item in ((Category)categoryTreeView.SelectedNode).Templates) {
availableTargetFrameworks.UnionWith(item.Template.SupportedTargetFrameworks);
}
targetFrameworkComboBox.Items.AddRange(
availableTargetFrameworks.Where(fx => fx.DisplayName != null && fx.IsAvailable())
.OrderBy(fx => fx.Name).ToArray());
}
if (targetFrameworkComboBox.Items.Count > 0) {
targetFrameworkComboBox.Visible = true;
@ -195,7 +190,7 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs @@ -195,7 +190,7 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs
if (categoryTreeView.SelectedNode != null) {
TargetFramework currentFramework = targetFrameworkComboBox.SelectedItem as TargetFramework;
foreach (TemplateItem item in ((Category)categoryTreeView.SelectedNode).Templates) {
if (currentFramework == null || item.Template.SupportsTargetFramework(currentFramework)) {
if (currentFramework == null || item.Template.SupportedTargetFrameworks.Contains(currentFramework) || !item.Template.SupportedTargetFrameworks.Any()) {
templateListView.Items.Add(item);
}
}
@ -274,8 +269,6 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs @@ -274,8 +269,6 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs
templateListView.View = smallIconsRadioButton.Checked ? View.List : View.LargeIcon;
}
public FileName NewProjectLocation;
public FileName NewSolutionLocation;
public ISolutionFolder SolutionFolder;
string CheckProjectName(string solution, string name, string location)
@ -333,16 +326,9 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs @@ -333,16 +326,9 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs
return;
}
ProjectCreateOptions cinfo = new ProjectCreateOptions();
if (!createNewSolution) {
cinfo.SolutionPath = ProjectService.OpenSolution.Directory;
cinfo.SolutionName = ProjectService.OpenSolution.Name;
} else {
cinfo.SolutionPath = DirectoryName.Create(NewSolutionDirectory);
cinfo.SolutionName = solution;
}
ProjectTemplateOptions cinfo = new ProjectTemplateOptions();
if (item.Template.HasSupportedTargetFrameworks) {
if (item.Template.SupportedTargetFrameworks.Any()) {
cinfo.TargetFramework = (TargetFramework)targetFrameworkComboBox.SelectedItem;
PropertyService.Set("Dialogs.NewProjectDialog.TargetFramework", cinfo.TargetFramework.Name);
}
@ -350,27 +336,19 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs @@ -350,27 +336,19 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs
cinfo.ProjectBasePath = DirectoryName.Create(NewProjectDirectory);
cinfo.ProjectName = name;
NewSolutionLocation = null;
NewProjectLocation = null;
if (createNewSolution) {
if (!SD.ProjectService.CloseSolution())
return;
ISolution createdSolution = item.Template.CreateSolution(cinfo);
if (createdSolution != null) {
NewSolutionLocation = createdSolution.FileName;
if (!SD.ProjectService.OpenSolution(createdSolution)) {
createdSolution.Dispose();
return;
}
}
result = item.Template.CreateAndOpenSolution(cinfo, NewSolutionDirectory, solution);
} else {
IProject project = item.Template.CreateProject(SD.ProjectService.CurrentSolution, cinfo);
NewProjectLocation = project.FileName;
SolutionFolder.Items.Add(project);
ProjectService.SaveSolution();
cinfo.Solution = SolutionFolder.ParentSolution;
cinfo.SolutionFolder = SolutionFolder;
result = item.Template.CreateProjects(cinfo);
cinfo.Solution.Save();
}
item.Template.RunOpenActions(cinfo);
if (result != null)
item.Template.RunOpenActions(result);
DialogResult = DialogResult.OK;
}

19
src/Main/Base/Project/Src/Internal/Templates/File/FileDescriptionTemplate.cs

@ -20,7 +20,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -20,7 +20,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
// Either content or contentData is set, the other is null
string content;
string binaryFileName;
FileName binaryFileName;
string itemType;
Dictionary<string, string> metadata = new Dictionary<string, string>();
@ -35,10 +35,13 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -35,10 +35,13 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
"name", "language", "buildAction", "src", "binary"
};
public FileDescriptionTemplate(XmlElement xml, string hintPath)
internal readonly IReadOnlyFileSystem FileSystem;
public FileDescriptionTemplate(XmlElement xml, IReadOnlyFileSystem fileSystem)
{
TemplateLoadException.AssertAttributeExists(xml, "name");
this.FileSystem = fileSystem;
name = xml.GetAttribute("name");
language = xml.GetAttribute("language");
if (xml.HasAttribute("buildAction")) {
@ -48,15 +51,15 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -48,15 +51,15 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
string attributeName = attribute.Name;
if (!knownAttributes.Contains(attributeName)) {
if (attributeName == "copyToOutputDirectory") {
ProjectTemplate.WarnObsoleteAttribute(xml, attributeName, "Use upper-case attribute names for MSBuild metadata values!");
ProjectTemplateImpl.WarnObsoleteAttribute(xml, attributeName, "Use upper-case attribute names for MSBuild metadata values!");
attributeName = "CopyToOutputDirectory";
}
if (attributeName == "dependentUpon") {
ProjectTemplate.WarnObsoleteAttribute(xml, attributeName, "Use upper-case attribute names for MSBuild metadata values!");
ProjectTemplateImpl.WarnObsoleteAttribute(xml, attributeName, "Use upper-case attribute names for MSBuild metadata values!");
attributeName = "DependentUpon";
}
if (attributeName == "subType") {
ProjectTemplate.WarnObsoleteAttribute(xml, attributeName, "Use upper-case attribute names for MSBuild metadata values!");
ProjectTemplateImpl.WarnObsoleteAttribute(xml, attributeName, "Use upper-case attribute names for MSBuild metadata values!");
attributeName = "SubType";
}
@ -64,12 +67,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -64,12 +67,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
}
if (xml.HasAttribute("src")) {
string fileName = Path.Combine(hintPath, StringParser.Parse(xml.GetAttribute("src")));
FileName fileName = FileName.Create(StringParser.Parse(xml.GetAttribute("src")));
try {
if (xml.HasAttribute("binary") && bool.Parse(xml.GetAttribute("binary"))) {
binaryFileName = fileName;
} else {
content = File.ReadAllText(fileName);
content = fileSystem.ReadAllText(fileName);
}
} catch (Exception e) {
content = "Error reading content from " + fileName + ":\n" + e.ToString();
@ -123,7 +126,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -123,7 +126,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
}
public string BinaryFileName {
public FileName BinaryFileName {
get {
return binaryFileName;
}

42
src/Main/Base/Project/Src/Internal/Templates/File/FileTemplate.cs

@ -219,11 +219,8 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -219,11 +219,8 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
}
public FileTemplate(string filename)
public FileTemplate(XmlDocument doc, IReadOnlyFileSystem fileSystem)
{
XmlDocument doc = new XmlDocument();
doc.Load(filename);
author = doc.DocumentElement.GetAttribute("author");
XmlElement config = doc.DocumentElement["Config"];
@ -290,14 +287,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -290,14 +287,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
fileoptions = doc.DocumentElement["AdditionalOptions"];
doc.DocumentElement.SetAttribute("fileName", filename); // used for template loading warnings
// load the files
XmlElement files = doc.DocumentElement["Files"];
XmlNodeList nodes = files.ChildNodes;
foreach (XmlNode filenode in nodes) {
if (filenode is XmlElement) {
this.files.Add(new FileDescriptionTemplate((XmlElement)filenode, Path.GetDirectoryName(filename)));
this.files.Add(new FileDescriptionTemplate((XmlElement)filenode, fileSystem));
}
}
}
@ -315,11 +310,11 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -315,11 +310,11 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
return null;
}
} else {
ProjectTemplate.WarnAttributeMissing(el, "path");
ProjectTemplateImpl.WarnAttributeMissing(el, "path");
return null;
}
default:
ProjectTemplate.WarnObsoleteNode(el, "Unknown action element is ignored");
ProjectTemplateImpl.WarnObsoleteNode(el, "Unknown action element is ignored");
return null;
}
}
@ -329,34 +324,5 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -329,34 +324,5 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
if (actions != null)
actions(options);
}
public static void UpdateTemplates()
{
string dataTemplateDir = Path.Combine(PropertyService.DataDirectory, "templates", "file");
List<string> files = FileUtility.SearchDirectory(dataTemplateDir, "*.xft");
foreach (string templateDirectory in AddInTree.BuildItems<string>(ProjectTemplate.TemplatePath, null, false)) {
if (!Directory.Exists(templateDirectory))
Directory.CreateDirectory(templateDirectory);
files.AddRange(FileUtility.SearchDirectory(templateDirectory, "*.xft"));
}
FileTemplates.Clear();
foreach (string file in files) {
try {
FileTemplates.Add(new FileTemplate(file));
} catch (XmlException ex) {
MessageService.ShowError("Error loading template file " + file + ":\n" + ex.Message);
} catch (TemplateLoadException ex) {
MessageService.ShowError("Error loading template file " + file + ":\n" + ex.ToString());
} catch(Exception e) {
MessageService.ShowException(e, "Error loading template file " + file + ".");
}
}
FileTemplates.Sort();
}
static FileTemplate()
{
UpdateTemplates();
}
}
}

43
src/Main/Base/Project/Src/Internal/Templates/Project/ProjectDescriptor.cs

@ -66,12 +66,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -66,12 +66,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
/// </summary>
/// <param name="element">The &lt;Project&gt; node of the xml template file.</param>
/// <param name="hintPath">The directory on which relative paths (e.g. for referenced files) are based.</param>
public ProjectDescriptor(XmlElement element, string hintPath)
public ProjectDescriptor(XmlElement element, IReadOnlyFileSystem fileSystem)
{
if (element == null)
throw new ArgumentNullException("element");
if (hintPath == null)
throw new ArgumentNullException("hintPath");
if (fileSystem == null)
throw new ArgumentNullException("fileSystem");
if (element.HasAttribute("name")) {
name = element.GetAttribute("name");
@ -80,18 +80,18 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -80,18 +80,18 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
languageName = element.GetAttribute("language");
if (string.IsNullOrEmpty(languageName)) {
ProjectTemplate.WarnAttributeMissing(element, "language");
ProjectTemplateImpl.WarnAttributeMissing(element, "language");
}
defaultPlatform = element.GetAttribute("defaultPlatform");
LoadElementChildren(element, hintPath);
LoadElementChildren(element, fileSystem);
}
#region Loading XML template
void LoadElementChildren(XmlElement parentElement, string hintPath)
void LoadElementChildren(XmlElement parentElement, IReadOnlyFileSystem fileSystem)
{
foreach (XmlElement node in ChildElements(parentElement)) {
LoadElement(node, hintPath);
LoadElement(node, fileSystem);
}
}
@ -100,11 +100,11 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -100,11 +100,11 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
return parentElement.ChildNodes.OfType<XmlElement>();
}
void LoadElement(XmlElement node, string hintPath)
void LoadElement(XmlElement node, IReadOnlyFileSystem fileSystem)
{
switch (node.Name) {
case "Options":
ProjectTemplate.WarnObsoleteNode(node, "Options are no longer supported, use properties instead.");
ProjectTemplateImpl.WarnObsoleteNode(node, "Options are no longer supported, use properties instead.");
break;
case "CreateActions":
LoadCreateActions(node);
@ -116,7 +116,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -116,7 +116,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
LoadProjectItems(node);
break;
case "Files":
LoadFiles(node, hintPath);
LoadFiles(node, fileSystem);
break;
case "Imports":
LoadImports(node);
@ -126,15 +126,18 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -126,15 +126,18 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
break;
case "Include":
TemplateLoadException.AssertAttributeExists(node, "src");
string includeFileName = Path.Combine(hintPath, node.GetAttribute("src"));
FileName includeFileName = FileName.Create(node.GetAttribute("src"));
try {
XmlDocument doc = new XmlDocument();
doc.Load(includeFileName);
using (var stream = fileSystem.OpenRead(includeFileName)) {
doc.Load(stream);
}
doc.DocumentElement.SetAttribute("fileName", includeFileName);
var fileSystemForInclude = new ReadOnlyChrootFileSystem(fileSystem, includeFileName.GetParentDirectory());
if (doc.DocumentElement.Name == "Include") {
LoadElementChildren(doc.DocumentElement, Path.GetDirectoryName(includeFileName));
LoadElementChildren(doc.DocumentElement, fileSystemForInclude);
} else {
LoadElement(doc.DocumentElement, Path.GetDirectoryName(includeFileName));
LoadElement(doc.DocumentElement, fileSystemForInclude);
}
} catch (XmlException ex) {
throw new TemplateLoadException("Error loading include file " + includeFileName, ex);
@ -183,7 +186,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -183,7 +186,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
};
} else {
ProjectTemplate.WarnAttributeMissing(el, "path");
ProjectTemplateImpl.WarnAttributeMissing(el, "path");
return null;
}
default:
@ -254,10 +257,10 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -254,10 +257,10 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
}
void LoadFiles(XmlElement filesElement, string hintPath)
void LoadFiles(XmlElement filesElement, IReadOnlyFileSystem fileSystem)
{
foreach (XmlElement fileElement in ChildElements(filesElement)) {
files.Add(new FileDescriptionTemplate(fileElement, hintPath));
files.Add(new FileDescriptionTemplate(fileElement, fileSystem));
}
}
#endregion
@ -265,8 +268,10 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -265,8 +268,10 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
#region Create new project from template
//Show prompt, create files from template, create project, execute command, save project
public IProject CreateProject(ISolution parentSolution, ProjectCreateOptions projectCreateOptions, string defaultLanguage)
public IProject CreateProject(ProjectTemplateResult templateResults, string defaultLanguage)
{
var projectCreateOptions = templateResults.Options;
var parentSolution = templateResults.Options.Solution;
IProject project = null;
bool success = false;
try
@ -509,7 +514,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -509,7 +514,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
SD.GetRequiredService<IProjectServiceRaiseEvents>().RaiseProjectCreated(new ProjectEventArgs(project));
projectCreateOptions.CreatedProjects.Add(project);
templateResults.NewProjects.Add(project);
success = true;
return project;
} finally {

185
src/Main/Base/Project/Src/Internal/Templates/Project/ProjectTemplate.cs

@ -2,67 +2,24 @@ @@ -2,67 +2,24 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Windows.Input;
using System.Xml;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Templates;
namespace ICSharpCode.SharpDevelop.Internal.Templates
{
public class ProjectCreateOptions
{
public DirectoryName SolutionPath { get; set; }
public DirectoryName ProjectBasePath { get; set; }
public string SolutionName { get; set; }
public string ProjectName { get; set; }
public TargetFramework TargetFramework { get; set; }
public IList<IProject> CreatedProjects { get; private set; }
public ProjectCreateOptions()
{
this.CreatedProjects = new List<IProject>();
}
}
/// <summary>
/// This class defines and holds the new project templates.
/// </summary>
internal class ProjectTemplate : IComparable
internal class ProjectTemplateImpl : ProjectTemplate
{
static List<ProjectTemplate> projectTemplates;
/// <summary>
/// Gets the list of project templates. Not thread-safe!
/// </summary>
public static ReadOnlyCollection<ProjectTemplate> ProjectTemplates {
get {
SD.MainThread.VerifyAccess();
#if DEBUG
// Always reload project templates if debugging.
// TODO: Make this a configurable option.
UpdateTemplates();
#else
if (projectTemplates == null) {
UpdateTemplates();
}
#endif
return projectTemplates.AsReadOnly();
}
}
string originator;
string created;
string lastmodified;
@ -70,34 +27,22 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -70,34 +27,22 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
string category;
string languagename;
string description;
string icon;
IImage icon;
string subcategory;
TargetFramework[] supportedTargetFrameworks;
internal bool HasSupportedTargetFrameworks {
get { return supportedTargetFrameworks != null; }
public override IEnumerable<TargetFramework> SupportedTargetFrameworks {
get { return supportedTargetFrameworks; }
}
internal bool SupportsTargetFramework(TargetFramework framework)
{
if (supportedTargetFrameworks == null)
return true;
// return true if framework is based on any of the supported target frameworks
return supportedTargetFrameworks.Any(framework.IsBasedOn);
}
bool newProjectDialogVisible = true;
int IComparable.CompareTo(object other)
public override bool IsVisible(ISolution solution)
{
ProjectTemplate pt = other as ProjectTemplate;
if (pt == null) return -1;
int res = category.CompareTo(pt.category);
if (res != 0) return res;
return name.CompareTo(pt.name);
return newProjectDialogVisible && (solution == null || projectDescriptor != null);
}
bool newProjectDialogVisible = true;
List<Action<ProjectCreateOptions>> openActions = new List<Action<ProjectCreateOptions>>();
List<Action<ProjectTemplateResult>> openActions = new List<Action<ProjectTemplateResult>>();
SolutionDescriptor solutionDescriptor = null;
ProjectDescriptor projectDescriptor = null;
@ -121,19 +66,19 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -121,19 +66,19 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
}
public string Name {
public override string Name {
get {
return name;
}
}
public string Category {
public override string Category {
get {
return category;
}
}
public string Subcategory {
public override string Subcategory {
get {
return subcategory;
}
@ -145,13 +90,13 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -145,13 +90,13 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
}
public string Description {
public override string Description {
get {
return description;
}
}
public string Icon {
public override IImage Icon {
get {
return icon;
}
@ -179,18 +124,9 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -179,18 +124,9 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
#endregion
protected ProjectTemplate(string fileName)
{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
LoadFromXml(doc.DocumentElement, fileName);
}
void LoadFromXml(XmlElement templateElement, string xmlFileName)
public ProjectTemplateImpl(XmlDocument doc, IReadOnlyFileSystem fileSystem)
{
// required for warning messages for unknown elements
templateElement.SetAttribute("fileName", xmlFileName);
var templateElement = doc.DocumentElement;
originator = templateElement.GetAttribute("originator");
created = templateElement.GetAttribute("created");
lastmodified = templateElement.GetAttribute("lastModified");
@ -218,25 +154,28 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -218,25 +154,28 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
if (config["Icon"] != null) {
icon = config["Icon"].InnerText;
icon = SD.ResourceService.GetImage(config["Icon"].InnerText);
}
if (config["SupportedTargetFrameworks"] != null) {
supportedTargetFrameworks =
var specifiedTargetFrameworks =
config["SupportedTargetFrameworks"].InnerText.Split(';')
.Select<string,TargetFramework>(TargetFramework.GetByName).ToArray();
supportedTargetFrameworks = TargetFramework.TargetFrameworks.Where(fx => specifiedTargetFrameworks.Any(s => fx.IsBasedOn(s))).ToArray();
} else {
supportedTargetFrameworks = new TargetFramework[0];
}
string hintPath = Path.GetDirectoryName(xmlFileName);
if (templateElement["Solution"] != null) {
solutionDescriptor = SolutionDescriptor.CreateSolutionDescriptor(templateElement["Solution"], hintPath);
solutionDescriptor = SolutionDescriptor.CreateSolutionDescriptor(templateElement["Solution"], fileSystem);
} else if (templateElement["Combine"] != null) {
solutionDescriptor = SolutionDescriptor.CreateSolutionDescriptor(templateElement["Combine"], hintPath);
solutionDescriptor = SolutionDescriptor.CreateSolutionDescriptor(templateElement["Combine"], fileSystem);
WarnObsoleteNode(templateElement["Combine"], "Use <Solution> instead!");
}
if (templateElement["Project"] != null) {
projectDescriptor = new ProjectDescriptor(templateElement["Project"], hintPath);
projectDescriptor = new ProjectDescriptor(templateElement["Project"], fileSystem);
}
if (solutionDescriptor == null && projectDescriptor == null
@ -248,20 +187,21 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -248,20 +187,21 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
// Read Actions;
if (templateElement["Actions"] != null) {
foreach (XmlElement el in templateElement["Actions"]) {
Action<ProjectCreateOptions> action = ReadAction(el);
Action<ProjectTemplateResult> action = ReadAction(el);
if (action != null)
openActions.Add(action);
}
}
}
static Action<ProjectCreateOptions> ReadAction(XmlElement el)
static Action<ProjectTemplateResult> ReadAction(XmlElement el)
{
switch (el.Name) {
case "Open":
if (el.HasAttribute("filename")) {
string fileName = el.GetAttribute("filename");
return projectCreateInformation => {
return projectTemplateResult => {
var projectCreateInformation = projectTemplateResult.Options;
string unresolvedFileName = StringParser.Parse(fileName, new StringTagPair("ProjectName", projectCreateInformation.ProjectName));
string path = Path.Combine(projectCreateInformation.ProjectBasePath, unresolvedFileName);
FileService.OpenFile(path);
@ -312,74 +252,29 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -312,74 +252,29 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
"'");
}
// string startupProject = null;
public ISolution CreateSolution(ProjectCreateOptions projectCreateInformation)
public override ProjectTemplateResult CreateProjects(ProjectTemplateOptions options)
{
LoggingService.Info("Creating solution from template '" + this.Category + "/" + this.Subcategory + "/" + this.Name + "'");
ISolution solution;
var result = new ProjectTemplateResult(options);
if (solutionDescriptor != null) {
solution = solutionDescriptor.CreateSolution(projectCreateInformation, this.languagename);
} else {
FileName fileName = FileName.Create(Path.Combine(projectCreateInformation.SolutionPath, projectCreateInformation.SolutionName + ".sln"));
solution = SD.ProjectService.CreateEmptySolutionFile(fileName);
IProject project = projectDescriptor.CreateProject(solution, projectCreateInformation, this.languagename);
if (!solutionDescriptor.AddContents(options.SolutionFolder, result, languagename))
return null;
}
if (projectDescriptor != null) {
IProject project = projectDescriptor.CreateProject(result, languagename);
if (project != null) {
solution.Items.Add(project);
solution.Save();
options.SolutionFolder.Items.Add(project);
} else {
solution.Dispose();
solution = null;
return null;
}
}
if (solution != null)
SD.GetRequiredService<IProjectServiceRaiseEvents>().RaiseSolutionCreated(new SolutionEventArgs(solution));
return solution;
}
public IProject CreateProject(ISolution solution, ProjectCreateOptions projectCreateInformation)
{
if (solution == null) {
throw new ArgumentNullException("solution");
}
if (solutionDescriptor != null) {
throw new InvalidOperationException("Cannot create an individual project from a solution template");
} else if (projectDescriptor != null) {
return projectDescriptor.CreateProject(solution, projectCreateInformation, this.languagename);
} else {
return null;
}
return result;
}
public void RunOpenActions(ProjectCreateOptions projectCreateInformation)
public override void RunOpenActions(ProjectTemplateResult result)
{
foreach (var action in openActions) {
action(projectCreateInformation);
}
}
public const string TemplatePath = "/SharpDevelop/BackendBindings/Templates";
public static void UpdateTemplates()
{
projectTemplates = new List<ProjectTemplate>();
string dataTemplateDir = Path.Combine(PropertyService.DataDirectory, "templates", "project");
List<string> files = FileUtility.SearchDirectory(dataTemplateDir, "*.xpt");
foreach (string templateDirectory in AddInTree.BuildItems<string>(TemplatePath, null, false)) {
files.AddRange(FileUtility.SearchDirectory(templateDirectory, "*.xpt"));
}
foreach (string fileName in files) {
try {
projectTemplates.Add(new ProjectTemplate(fileName));
} catch (XmlException e) {
MessageService.ShowError(ResourceService.GetString("Internal.Templates.ProjectTemplate.LoadingError") + "\n(" + fileName + ")\n" + e.Message);
} catch (TemplateLoadException e) {
MessageService.ShowError(ResourceService.GetString("Internal.Templates.ProjectTemplate.LoadingError") + "\n(" + fileName + ")\n" + e.ToString());
} catch (Exception e) {
MessageService.ShowException(e, ResourceService.GetString("Internal.Templates.ProjectTemplate.LoadingError") + "\n(" + fileName + ")\n");
}
action(result);
}
projectTemplates.Sort();
}
}
}

47
src/Main/Base/Project/Src/Internal/Templates/Project/SolutionDescriptor.cs

@ -8,6 +8,7 @@ using System.Xml; @@ -8,6 +8,7 @@ using System.Xml;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Templates;
namespace ICSharpCode.SharpDevelop.Internal.Templates
{
@ -21,31 +22,31 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -21,31 +22,31 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
internal List<ProjectDescriptor> projectDescriptors = new List<ProjectDescriptor>();
internal List<SolutionFolderDescriptor> solutionFoldersDescriptors = new List<SolutionFolderDescriptor>();
internal void Read(XmlElement element, string hintPath)
internal void Read(XmlElement element, IReadOnlyFileSystem fileSystem)
{
name = element.GetAttribute("name");
foreach (XmlNode node in element.ChildNodes) {
switch (node.Name) {
case "Project":
projectDescriptors.Add(new ProjectDescriptor((XmlElement)node, hintPath));
projectDescriptors.Add(new ProjectDescriptor((XmlElement)node, fileSystem));
break;
case "SolutionFolder":
solutionFoldersDescriptors.Add(new SolutionFolderDescriptor((XmlElement)node, hintPath));
solutionFoldersDescriptors.Add(new SolutionFolderDescriptor((XmlElement)node, fileSystem));
break;
}
}
}
internal bool AddContents(ISolutionFolder parentFolder, ProjectCreateOptions projectCreateOptions, string defaultLanguage)
internal bool AddContents(ISolutionFolder parentFolder, ProjectTemplateResult templateResult, string defaultLanguage)
{
// Create sub projects
foreach (SolutionFolderDescriptor folderDescriptor in solutionFoldersDescriptors) {
ISolutionFolder folder = parentFolder.CreateFolder(folderDescriptor.name);
if (!folderDescriptor.AddContents(folder, projectCreateOptions, defaultLanguage))
if (!folderDescriptor.AddContents(folder, templateResult, defaultLanguage))
return false;
}
foreach (ProjectDescriptor projectDescriptor in projectDescriptors) {
IProject newProject = projectDescriptor.CreateProject(parentFolder.ParentSolution, projectCreateOptions, defaultLanguage);
IProject newProject = projectDescriptor.CreateProject(templateResult, defaultLanguage);
if (newProject == null)
return false;
parentFolder.Items.Add(newProject);
@ -53,9 +54,9 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -53,9 +54,9 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
return true;
}
public SolutionFolderDescriptor(XmlElement element, string hintPath)
public SolutionFolderDescriptor(XmlElement element, IReadOnlyFileSystem fileSystem)
{
Read(element, hintPath);
Read(element, fileSystem);
}
public SolutionFolderDescriptor(string name)
@ -86,34 +87,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -86,34 +87,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
this.name = name;
}
public ISolution CreateSolution(ProjectCreateOptions projectCreateInformation, string defaultLanguage)
internal bool AddContents(ISolutionFolder parentFolder, ProjectTemplateResult templateResult, string defaultLanguage)
{
string newSolutionName = StringParser.Parse(name, new StringTagPair("ProjectName", projectCreateInformation.SolutionName));
string solutionLocation = Path.Combine(projectCreateInformation.SolutionPath, newSolutionName + ".sln");
ISolution newSolution = SD.ProjectService.CreateEmptySolutionFile(FileName.Create(solutionLocation));
if (!mainFolder.AddContents(newSolution, projectCreateInformation, defaultLanguage)) {
newSolution.Dispose();
return null;
}
// Save solution
if (File.Exists(solutionLocation)) {
string question = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Internal.Templates.CombineDescriptor.OverwriteProjectQuestion}",
new StringTagPair("combineLocation", solutionLocation));
if (MessageService.AskQuestion(question)) {
newSolution.Save();
}
} else {
newSolution.Save();
}
return newSolution;
return mainFolder.AddContents(parentFolder, templateResult, defaultLanguage);
}
public static SolutionDescriptor CreateSolutionDescriptor(XmlElement element, string hintPath)
public static SolutionDescriptor CreateSolutionDescriptor(XmlElement element, IReadOnlyFileSystem fileSystem)
{
SolutionDescriptor solutionDescriptor = new SolutionDescriptor(element.Attributes["name"].InnerText);
@ -121,7 +100,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -121,7 +100,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
solutionDescriptor.startupProject = element["Options"]["StartupProject"].InnerText;
}
solutionDescriptor.mainFolder.Read(element, hintPath);
solutionDescriptor.mainFolder.Read(element, fileSystem);
return solutionDescriptor;
}
}

15
src/Main/Base/Project/Src/Internal/Templates/TemplateCategorySortOrderFile.cs

@ -14,7 +14,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -14,7 +14,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
/// File that defines the sort order for the file and project template
/// categories.
/// </summary>
public class TemplateCategorySortOrderFile
class TemplateCategorySortOrderFile
{
public const int UndefinedSortOrder = -1;
@ -116,9 +116,10 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -116,9 +116,10 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
projectCategorySortOrderFiles = new List<TemplateCategorySortOrderFile>();
string dataTemplateDir = Path.Combine(PropertyService.DataDirectory, "templates", "project");
List<string> files = FileUtility.SearchDirectory(dataTemplateDir, ProjectCategorySortOrderFileName);
foreach (string templateDirectory in AddInTree.BuildItems<string>(ProjectTemplate.TemplatePath, null, false)) {
files.AddRange(FileUtility.SearchDirectory(templateDirectory, ProjectCategorySortOrderFileName));
}
#warning Re-implement addin-defined category sort order
// foreach (string templateDirectory in AddInTree.BuildItems<string>(ProjectTemplate.TemplatePath, null, false)) {
// files.AddRange(FileUtility.SearchDirectory(templateDirectory, ProjectCategorySortOrderFileName));
// }
foreach (string fileName in files) {
try {
projectCategorySortOrderFiles.Add(new TemplateCategorySortOrderFile(fileName));
@ -133,9 +134,9 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -133,9 +134,9 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
fileCategorySortOrderFiles = new List<TemplateCategorySortOrderFile>();
string dataTemplateDir = Path.Combine(PropertyService.DataDirectory, "templates", "file");
List<string> files = FileUtility.SearchDirectory(dataTemplateDir, FileCategorySortOrderFileName);
foreach (string templateDirectory in AddInTree.BuildItems<string>(ProjectTemplate.TemplatePath, null, false)) {
files.AddRange(FileUtility.SearchDirectory(templateDirectory, FileCategorySortOrderFileName));
}
// foreach (string templateDirectory in AddInTree.BuildItems<string>(ProjectTemplate.TemplatePath, null, false)) {
// files.AddRange(FileUtility.SearchDirectory(templateDirectory, FileCategorySortOrderFileName));
// }
foreach (string fileName in files) {
try {
fileCategorySortOrderFiles.Add(new TemplateCategorySortOrderFile(fileName));

3
src/Main/Base/Project/Templates/FileTemplateResult.cs

@ -8,9 +8,6 @@ using ICSharpCode.SharpDevelop.Project; @@ -8,9 +8,6 @@ using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Templates
{
/// <summary>
/// Description of FileTemplateResult.
/// </summary>
public class FileTemplateResult
{
readonly FileTemplateOptions options;

10
src/Main/Base/Project/Templates/ITemplateService.cs

@ -21,6 +21,11 @@ namespace ICSharpCode.SharpDevelop.Templates @@ -21,6 +21,11 @@ namespace ICSharpCode.SharpDevelop.Templates
/// </summary>
IEnumerable<ProjectTemplate> ProjectTemplates { get; }
/// <summary>
/// Reloads the <see cref="FileTemplates"/> and <see cref="ProjectTemplates"/>.
/// </summary>
void UpdateTemplates();
/// <summary>
/// Loads a file template (.xft or .xpt file) from disk.
/// </summary>
@ -34,10 +39,9 @@ namespace ICSharpCode.SharpDevelop.Templates @@ -34,10 +39,9 @@ namespace ICSharpCode.SharpDevelop.Templates
/// <param name="fileSystem">File system used to open referenced input files.
/// This should usually be a <see cref="ReadOnlyChrootFileSystem"/> so that the file template
/// can use relative paths.
/// The template will keep a reference to the file system instance and use it when it is used to create
/// files/projects.
/// The template will keep a reference to the file system instance and use it to create files/projects.
/// </param>
/// <returns><see cref="FileTemplate"/> or <see cref="ProjectTemplate"/> instance.</returns>
TemplateBase LoadTemplate(TextReader textReader, IReadOnlyFileSystem fileSystem);
TemplateBase LoadTemplate(Stream stream, IReadOnlyFileSystem fileSystem);
}
}

44
src/Main/Base/Project/Templates/ProjectTemplate.cs

@ -2,12 +2,54 @@ @@ -2,12 +2,54 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Templates
{
public abstract class ProjectTemplate : TemplateBase
{
public ProjectTemplate()
/// <summary>
/// Gets whether this template is available within the specified solution.
/// </summary>
/// <param name="solution">The solution to which the new project should be added.
/// Can be <c>null</c> when creating a new solution.</param>
public virtual bool IsVisible(ISolution solution)
{
return true;
}
public virtual IEnumerable<TargetFramework> SupportedTargetFrameworks {
get { return Enumerable.Empty<TargetFramework>(); }
}
public abstract ProjectTemplateResult CreateProjects(ProjectTemplateOptions options);
internal ProjectTemplateResult CreateAndOpenSolution(ProjectTemplateOptions options, string solutionDirectory, string solutionName)
{
FileName solutionFileName = FileName.Create(Path.Combine(solutionDirectory, solutionName + ".sln"));
ISolution createdSolution = SD.ProjectService.CreateEmptySolutionFile(solutionFileName);
options.Solution = createdSolution;
options.SolutionFolder = createdSolution;
var result = CreateProjects(options);
if (result == null || !SD.ProjectService.OpenSolution(createdSolution)) {
createdSolution.Dispose();
return null;
} else {
createdSolution.Save();
SD.GetRequiredService<IProjectServiceRaiseEvents>().RaiseSolutionCreated(new SolutionEventArgs(createdSolution));
return result;
}
}
/// <summary>
/// Runs the actions after the newly created solution is opened in the IDE.
/// </summary>
public virtual void RunOpenActions(ProjectTemplateResult result)
{
}
}

21
src/Main/Base/Project/Templates/ProjectTemplateOptions.cs

@ -0,0 +1,21 @@ @@ -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.Collections.Generic;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Templates
{
public class ProjectTemplateOptions
{
public DirectoryName ProjectBasePath { get; set; }
public ISolution Solution { get; set; }
public ISolutionFolder SolutionFolder { get; set; }
public string ProjectName { get; set; }
public TargetFramework TargetFramework { get; set; }
internal string SolutionName { get { return Solution.Name; } }
}
}

17
src/Main/Base/Project/Templates/ProjectTemplateResult.cs

@ -12,5 +12,22 @@ namespace ICSharpCode.SharpDevelop.Templates @@ -12,5 +12,22 @@ namespace ICSharpCode.SharpDevelop.Templates
/// </summary>
public class ProjectTemplateResult
{
readonly ProjectTemplateOptions options;
readonly IList<IProject> newProjects = new List<IProject>();
public ProjectTemplateResult(ProjectTemplateOptions options)
{
if (options == null)
throw new ArgumentNullException("options");
this.options = options;
}
public ProjectTemplateOptions Options {
get { return options; }
}
public IList<IProject> NewProjects {
get { return newProjects; }
}
}
}

83
src/Main/Base/Project/Util/EmbeddedResourceFileSystem.cs

@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
// 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.IO;
using System.Linq;
using System.Reflection;
using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// Treats embedded resources as a file system.
/// </summary>
public class EmbeddedResourceFileSystem : IReadOnlyFileSystem
{
readonly Assembly[] assemblies;
readonly string prefix;
Lazy<List<FileName>> fileNames;
public EmbeddedResourceFileSystem(Assembly[] assemblies, string resourceNamespace)
{
if (assemblies == null)
throw new ArgumentNullException("assemblies");
if (resourceNamespace == null)
throw new ArgumentNullException("resourceNamespace");
this.assemblies = assemblies;
this.prefix = resourceNamespace + ".";
this.fileNames = new Lazy<List<FileName>>(GetFileNames);
}
List<FileName> GetFileNames()
{
List<FileName> result = new List<FileName>();
foreach (Assembly asm in assemblies) {
foreach (string resourceName in asm.GetManifestResourceNames()) {
if (resourceName.StartsWith(prefix, StringComparison.Ordinal)) {
result.Add(FileName.Create(resourceName.Substring(prefix.Length)));
}
}
}
return result;
}
public bool FileExists(FileName path)
{
return fileNames.Value.Contains(path);
}
bool IReadOnlyFileSystem.DirectoryExists(DirectoryName path)
{
return false;
}
string ToResourceName(FileName fileName)
{
return prefix + fileName.ToString().Replace('\\', '.');
}
public Stream OpenRead(FileName fileName)
{
string name = ToResourceName(fileName);
foreach (var asm in assemblies) {
Stream stream = asm.GetManifestResourceStream(name);
if (stream != null)
return stream;
}
throw new FileNotFoundException("Resource '" + name + "' not found.");
}
public TextReader OpenText(FileName fileName)
{
return new StreamReader(OpenRead(fileName));
}
public IEnumerable<FileName> GetFiles(DirectoryName directory, string searchPattern, SearchOption searchOption)
{
return fileNames.Value.Where(fn => FileUtility.IsBaseDirectory(directory, fn)
&& FileUtility.MatchesPattern(fn.GetFileName(), searchPattern));
}
}
}

18
src/Main/Base/Project/Util/IImage.cs

@ -76,5 +76,23 @@ namespace ICSharpCode.SharpDevelop @@ -76,5 +76,23 @@ namespace ICSharpCode.SharpDevelop
return SD.ResourceService.GetIcon(resourceName);
}
}
public override bool Equals(object obj)
{
ResourceServiceImage other = obj as ResourceServiceImage;
if (other == null)
return false;
return this.resourceName == other.resourceName;
}
public override int GetHashCode()
{
return resourceName.GetHashCode();
}
public override string ToString()
{
return string.Format("[ResourceServiceImage {0}]", resourceName);
}
}
}

1
src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj

@ -97,7 +97,6 @@ @@ -97,7 +97,6 @@
<Compile Include="Project\SolutionTests.cs" />
<Compile Include="Project\SolutionWriterTests.cs" />
<Compile Include="PropertyPadSortingTests.cs" />
<Compile Include="ReadOnlyDocumentTests.cs" />
<Compile Include="ReflectionLayerTests.cs" />
<Compile Include="GenericResolverTests.cs" />
<Compile Include="InnerClassesResolverTests.cs" />

63
src/Main/Base/Test/ReadOnlyDocumentTests.cs

@ -1,63 +0,0 @@ @@ -1,63 +0,0 @@
#warning
//// 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.NRefactory;
//using ICSharpCode.SharpDevelop.Editor;
//using NUnit.Framework;
//
//namespace ICSharpCode.SharpDevelop.Tests
//{
// [TestFixture]
// public class ReadOnlyDocumentTests
// {
// [Test]
// public void EmptyReadOnlyDocument()
// {
// IDocument document = DocumentUtilitites.LoadReadOnlyDocumentFromBuffer(new StringTextBuffer(string.Empty));
// Assert.AreEqual(string.Empty, document.Text);
// Assert.AreEqual(0, document.TextLength);
// Assert.AreEqual(1, document.TotalNumberOfLines);
// Assert.AreEqual(0, document.PositionToOffset(1, 1));
// Assert.AreEqual(new Location(1, 1), document.OffsetToPosition(0));
//
// Assert.AreEqual(0, document.GetLine(1).Offset);
// Assert.AreEqual(0, document.GetLine(1).EndOffset);
// Assert.AreEqual(0, document.GetLine(1).Length);
// Assert.AreEqual(0, document.GetLine(1).TotalLength);
// Assert.AreEqual(0, document.GetLine(1).DelimiterLength);
// Assert.AreEqual(1, document.GetLine(1).LineNumber);
// }
//
// [Test]
// public void SimpleDocument()
// {
// string text = "Hello\nWorld!\r\n";
// IDocument document = DocumentUtilitites.LoadReadOnlyDocumentFromBuffer(new StringTextBuffer(text));
// Assert.AreEqual(text, document.Text);
// Assert.AreEqual(3, document.TotalNumberOfLines);
//
// Assert.AreEqual(0, document.GetLine(1).Offset);
// Assert.AreEqual(5, document.GetLine(1).EndOffset);
// Assert.AreEqual(5, document.GetLine(1).Length);
// Assert.AreEqual(6, document.GetLine(1).TotalLength);
// Assert.AreEqual(1, document.GetLine(1).DelimiterLength);
// Assert.AreEqual(1, document.GetLine(1).LineNumber);
//
// Assert.AreEqual(6, document.GetLine(2).Offset);
// Assert.AreEqual(12, document.GetLine(2).EndOffset);
// Assert.AreEqual(6, document.GetLine(2).Length);
// Assert.AreEqual(8, document.GetLine(2).TotalLength);
// Assert.AreEqual(2, document.GetLine(2).DelimiterLength);
// Assert.AreEqual(2, document.GetLine(2).LineNumber);
//
// Assert.AreEqual(14, document.GetLine(3).Offset);
// Assert.AreEqual(14, document.GetLine(3).EndOffset);
// Assert.AreEqual(0, document.GetLine(3).Length);
// Assert.AreEqual(0, document.GetLine(3).TotalLength);
// Assert.AreEqual(0, document.GetLine(3).DelimiterLength);
// Assert.AreEqual(3, document.GetLine(3).LineNumber);
// }
// }
//}

37
src/Main/Core/Project/Src/Services/FileUtility/FileUtility.Minimal.cs

@ -35,14 +35,19 @@ namespace ICSharpCode.Core @@ -35,14 +35,19 @@ namespace ICSharpCode.Core
}
char outputSeparator = isWeb ? '/' : System.IO.Path.DirectorySeparatorChar;
bool isRelative;
StringBuilder result = new StringBuilder();
if (isWeb == false && fileName.StartsWith(@"\\") || fileName.StartsWith("//")) {
if (isWeb == false && fileName.StartsWith(@"\\", StringComparison.Ordinal) || fileName.StartsWith("//", StringComparison.Ordinal)) {
// UNC path
i = 2;
result.Append(outputSeparator);
isRelative = false;
} else {
i = 0;
isRelative = !isWeb && (fileName.Length < 2 || fileName[1] != ':');
}
int levelsBack = 0;
int segmentStartPos = i;
for (; i <= fileName.Length; i++) {
if (i == fileName.Length || fileName[i] == '/' || fileName[i] == '\\') {
@ -50,8 +55,7 @@ namespace ICSharpCode.Core @@ -50,8 +55,7 @@ namespace ICSharpCode.Core
switch (segmentLength) {
case 0:
// ignore empty segment (if not in web mode)
// On unix, don't ignore empty segment if i==0
if (isWeb || (i == 0 && Environment.OSVersion.Platform == PlatformID.Unix)) {
if (isWeb) {
result.Append(outputSeparator);
}
break;
@ -69,6 +73,11 @@ namespace ICSharpCode.Core @@ -69,6 +73,11 @@ namespace ICSharpCode.Core
for (j = result.Length - 1; j >= 0 && result[j] != outputSeparator; j--);
if (j > 0) {
result.Length = j;
} else if (isRelative) {
if (result.Length == 0)
levelsBack++;
else
result.Length = 0;
}
break;
} else {
@ -84,12 +93,19 @@ namespace ICSharpCode.Core @@ -84,12 +93,19 @@ namespace ICSharpCode.Core
}
}
if (isWeb == false) {
if (isRelative) {
for (int j = 0; j < levelsBack; j++) {
result.Insert(0, ".." + outputSeparator);
}
}
if (result.Length > 0 && result[result.Length - 1] == outputSeparator) {
result.Length -= 1;
}
if (result.Length == 2 && result[1] == ':') {
result.Append(outputSeparator);
}
if (result.Length == 0)
return ".";
}
return result.ToString();
}
@ -105,10 +121,21 @@ namespace ICSharpCode.Core @@ -105,10 +121,21 @@ namespace ICSharpCode.Core
{
if (baseDirectory == null || testDirectory == null)
return false;
baseDirectory = NormalizePath(baseDirectory) + Path.DirectorySeparatorChar;
testDirectory = NormalizePath(testDirectory) + Path.DirectorySeparatorChar;
baseDirectory = NormalizePath(baseDirectory);
if (baseDirectory == ".")
return !Path.IsPathRooted(testDirectory);
baseDirectory = AddTrailingSeparator(baseDirectory);
testDirectory = AddTrailingSeparator(NormalizePath(testDirectory));
return testDirectory.StartsWith(baseDirectory, StringComparison.OrdinalIgnoreCase);
}
static string AddTrailingSeparator(string input)
{
if (input[input.Length - 1] == Path.DirectorySeparatorChar)
return input;
else
return input + Path.DirectorySeparatorChar.ToString();
}
}
}

27
src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs

@ -276,30 +276,29 @@ namespace ICSharpCode.Core @@ -276,30 +276,29 @@ namespace ICSharpCode.Core
baseDirectoryPath = NormalizePath(baseDirectoryPath);
absPath = NormalizePath(absPath);
string[] bPath = baseDirectoryPath.Split(separators);
string[] aPath = absPath.Split(separators);
string[] bPath = baseDirectoryPath != "." ? baseDirectoryPath.Split(separators) : new string[0];
string[] aPath = absPath != "." ? absPath.Split(separators) : new string[0];
int indx = 0;
for(; indx < Math.Min(bPath.Length, aPath.Length); ++indx){
if(!bPath[indx].Equals(aPath[indx], StringComparison.OrdinalIgnoreCase))
break;
}
if (indx == 0) {
return absPath;
}
// if (indx == 0) {
// return absPath;
// }
if(indx == bPath.Length && indx == aPath.Length) {
return ".";
}
StringBuilder erg = new StringBuilder();
if(indx == bPath.Length) {
// erg.Append('.');
// erg.Append(Path.DirectorySeparatorChar);
} else {
for (int i = indx; i < bPath.Length; ++i) {
erg.Append("..");
erg.Append(Path.DirectorySeparatorChar);
}
for (int i = indx; i < bPath.Length; ++i) {
erg.Append("..");
erg.Append(Path.DirectorySeparatorChar);
}
erg.Append(String.Join(Path.DirectorySeparatorChar.ToString(), aPath, indx, aPath.Length-indx));
if (erg[erg.Length - 1] == Path.DirectorySeparatorChar)
erg.Length -= 1;
return erg.ToString();
}

5
src/Main/Core/Project/Src/Services/FileUtility/PathName.cs

@ -57,7 +57,10 @@ namespace ICSharpCode.Core @@ -57,7 +57,10 @@ namespace ICSharpCode.Core
/// </remarks>
public DirectoryName GetParentDirectory()
{
return DirectoryName.Create(Path.GetDirectoryName(normalizedPath));
if (normalizedPath.Length < 2 || normalizedPath[1] != ':')
return DirectoryName.Create(Path.Combine(normalizedPath, ".."));
else
return DirectoryName.Create(Path.GetDirectoryName(normalizedPath));
}
}
}

22
src/Main/Core/Test/FileNameTests.cs

@ -0,0 +1,22 @@ @@ -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;
using NUnit.Framework;
namespace ICSharpCode.Core.Tests
{
[TestFixture]
public class FileNameTests
{
[Test]
public void TestGetParentDirectory()
{
Assert.AreEqual(@"c:\", FileName.Create("c:\\file.txt").GetParentDirectory().ToString());
Assert.IsNull(DirectoryName.Create("c:\\").GetParentDirectory());
Assert.AreEqual("relpath", FileName.Create("relpath\\file.txt").GetParentDirectory().ToString());
Assert.AreEqual(".", FileName.Create("file.txt").GetParentDirectory().ToString());
Assert.AreEqual("..", FileName.Create("..\\file.txt").GetParentDirectory().ToString());
}
}
}

29
src/Main/Core/Test/AddInTreeTests/ExtPathTests.cs → src/Main/Core/Test/FileUtilityTests.cs

@ -48,6 +48,14 @@ namespace ICSharpCode.Core.Tests.AddInTreeTests.Tests @@ -48,6 +48,14 @@ namespace ICSharpCode.Core.Tests.AddInTreeTests.Tests
Assert.AreEqual(@"http://danielgrunwald.de/path/", FileUtility.NormalizePath(@"http://danielgrunwald.de/path/"));
Assert.AreEqual(@"browser://http://danielgrunwald.de/path/", FileUtility.NormalizePath(@"browser://http://danielgrunwald.de/wrongpath/../path/"));
}
[Test]
public void NormalizePath_Relative()
{
Assert.AreEqual(@"..\b", FileUtility.NormalizePath(@"..\a\..\b"));
Assert.AreEqual(@".", FileUtility.NormalizePath(@"."));
Assert.AreEqual(@".", FileUtility.NormalizePath(@"a\.."));
}
#endregion
[Test]
@ -69,6 +77,15 @@ namespace ICSharpCode.Core.Tests.AddInTreeTests.Tests @@ -69,6 +77,15 @@ namespace ICSharpCode.Core.Tests.AddInTreeTests.Tests
Assert.IsFalse(FileUtility.IsBaseDirectory(@"C:\b", @"C:\a\b\hello"));
Assert.IsFalse(FileUtility.IsBaseDirectory(@"C:\a\b\hello", @"C:\b"));
Assert.IsFalse(FileUtility.IsBaseDirectory(@"C:\a\x\fwufhweoe", @"C:\a\x\fwuFHweoex\a\b\hello"));
Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\", @"C:\"));
Assert.IsTrue(FileUtility.IsBaseDirectory(@"C:\", @"C:\a\b\hello"));
Assert.IsFalse(FileUtility.IsBaseDirectory(@"C:\", @"D:\a\b\hello"));
Assert.IsTrue(FileUtility.IsBaseDirectory(@".", @"a\b"));
Assert.IsTrue(FileUtility.IsBaseDirectory(@".", @"a"));
// Assert.IsFalse(FileUtility.IsBaseDirectory(@".", @"..\a"));
// Assert.IsFalse(FileUtility.IsBaseDirectory(@".", @".."));
Assert.IsFalse(FileUtility.IsBaseDirectory(@".", @"c:\"));
}
[Test]
@ -84,6 +101,8 @@ namespace ICSharpCode.Core.Tests.AddInTreeTests.Tests @@ -84,6 +101,8 @@ namespace ICSharpCode.Core.Tests.AddInTreeTests.Tests
Assert.AreEqual(@"blub", FileUtility.GetRelativePath(@"C:\hello\.\..\a", @"C:\.\a\blub"));
Assert.AreEqual(@"..\a\blub", FileUtility.GetRelativePath(@"C:\.\.\.\.\hello", @"C:\.\blub\.\..\.\a\.\blub"));
Assert.AreEqual(@"..\a\blub", FileUtility.GetRelativePath(@"C:\.\.\.\.\hello\", @"C:\.\blub\.\..\.\a\.\blub"));
Assert.AreEqual(@".", FileUtility.GetRelativePath(@"C:\hello", @"C:\.\hello"));
Assert.AreEqual(@".", FileUtility.GetRelativePath(@"C:\", @"C:\"));
// casing troubles
Assert.AreEqual(@"blub", FileUtility.GetRelativePath(@"C:\hello\.\..\A", @"C:\.\a\blub"));
@ -94,6 +113,16 @@ namespace ICSharpCode.Core.Tests.AddInTreeTests.Tests @@ -94,6 +113,16 @@ namespace ICSharpCode.Core.Tests.AddInTreeTests.Tests
Assert.AreEqual("http://example.com/vdir/", FileUtility.GetRelativePath("C:\\temp", "http://example.com/vdir/"));
}
[Test]
public void RelativeGetRelativePath()
{
// Relative path
Assert.AreEqual(@"a", FileUtility.GetRelativePath(@".", @"a"));
Assert.AreEqual(@"..", FileUtility.GetRelativePath(@"a", @"."));
Assert.AreEqual(@"..\b", FileUtility.GetRelativePath(@"a", @"b"));
// Assert.AreEqual(@"..\..", FileUtility.GetRelativePath(@"a", @".."));
}
[Test]
public void TestIsEqualFile()
{

3
src/Main/Core/Test/ICSharpCode.Core.Tests.csproj

@ -59,10 +59,11 @@ @@ -59,10 +59,11 @@
<ItemGroup>
<Compile Include="AddInTreeTests\RuntimeLoadAssemblyTests.cs" />
<Compile Include="AssemblyInfo.cs" />
<Compile Include="FileNameTests.cs" />
<Compile Include="FileUtilityTests.cs" />
<Compile Include="TopologicalSortTest.cs" />
<Compile Include="StringParserTests.cs" />
<Compile Include="AddInTreeTests\AddInTreeLoadingTests.cs" />
<Compile Include="AddInTreeTests\ExtPathTests.cs" />
<Compile Include="InvalidDirectoryNameTests.cs" />
<Compile Include="Utils\DerivedRuntime.cs" />
<Compile Include="Utils\Tests\DerivedRuntimeTests.cs" />

2
src/Main/SharpDevelop/Services/UIService.cs

@ -62,7 +62,7 @@ namespace ICSharpCode.SharpDevelop @@ -62,7 +62,7 @@ namespace ICSharpCode.SharpDevelop
// show the dialog to request project type and name
if (npdlg.ShowDialog(SD.WinForms.MainWin32Window) == DialogResult.OK) {
return new ProjectTemplateResult();
return npdlg.result;
} else {
return null;
}

1
src/Main/SharpDevelop/SharpDevelop.csproj

@ -150,6 +150,7 @@ @@ -150,6 +150,7 @@
<Compile Include="Startup\App.xaml.cs" />
<Compile Include="Startup\SharpDevelopMain.cs" />
<Compile Include="Startup\SplashScreen.cs" />
<Compile Include="Templates\TemplateFileDoozer.cs" />
<Compile Include="Templates\TemplateService.cs" />
<Compile Include="WinForms\SDWindowsFormsHost.cs" />
<Compile Include="WinForms\WinFormsMenuService.cs" />

77
src/Main/SharpDevelop/Templates/TemplateFileDoozer.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
// 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;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Templates
{
/// <summary>
/// Creates code completion bindings that manage code completion for one language.
/// </summary>
/// <attribute name="resourcePath" use="optional">
/// Namespace containing .xft and .xpt files as embedded resources.
/// </attribute>
/// <usage>Only in /SharpDevelop/BackendBindings/Templates</usage>
/// <returns>
/// The <see cref="TemplateBase"/> instance loaded from the template file.
/// </returns>
class TemplateFileDoozer : IDoozer
{
public bool HandleConditions {
get { return false; }
}
IReadOnlyFileSystem GetFileSystem(BuildItemArgs args)
{
string resourceNamespace = args.Codon["resourceNamespace"];
if (!string.IsNullOrEmpty(resourceNamespace)) {
args.AddIn.LoadRuntimeAssemblies();
var assemblies = args.AddIn.Runtimes.Select(r => r.LoadedAssembly).Where(asm => asm != null).ToArray();
return new EmbeddedResourceFileSystem(assemblies, resourceNamespace);
}
string path = args.Codon["path"];
if (!string.IsNullOrEmpty(path)) {
path = Path.Combine(Path.GetDirectoryName(args.AddIn.FileName), path);
return new ReadOnlyChrootFileSystem(SD.FileSystem, DirectoryName.Create(path));
}
throw new InvalidOperationException("Missing 'resourceNamespace' or 'path' attribute.");
}
public object BuildItem(BuildItemArgs args)
{
var fileSystem = GetFileSystem(args);
var templates = new List<TemplateBase>();
foreach (var fileName in fileSystem.GetFiles(DirectoryName.Create("."), "*.xpt", SearchOption.AllDirectories)) {
using (var stream = fileSystem.OpenRead(fileName)) {
templates.Add(SD.Templates.LoadTemplate(stream, fileSystem));
}
}
if (templates.Count == 1)
return templates[0];
else
return new MultipleItems(templates);
}
sealed class MultipleItems : IBuildItemsModifier
{
readonly IEnumerable items;
public MultipleItems(IEnumerable items)
{
this.items = items;
}
public void Apply(IList outputItems)
{
foreach (var item in items)
outputItems.Add(item);
}
}
}
}

22
src/Main/SharpDevelop/Templates/TemplateService.cs

@ -8,6 +8,7 @@ using System.Linq; @@ -8,6 +8,7 @@ using System.Linq;
using System.Xml;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Internal.Templates;
namespace ICSharpCode.SharpDevelop.Templates
{
@ -30,6 +31,12 @@ namespace ICSharpCode.SharpDevelop.Templates @@ -30,6 +31,12 @@ namespace ICSharpCode.SharpDevelop.Templates
get { return allTemplates.Value.OfType<ProjectTemplate>(); }
}
public void UpdateTemplates()
{
var newTemplates = LoadTemplates();
allTemplates = new Lazy<IReadOnlyList<TemplateBase>>(() => newTemplates);
}
IReadOnlyList<TemplateBase> LoadTemplates()
{
return SD.AddInTree.BuildItems<TemplateBase>(TemplatePath, this, false);
@ -38,15 +45,22 @@ namespace ICSharpCode.SharpDevelop.Templates @@ -38,15 +45,22 @@ namespace ICSharpCode.SharpDevelop.Templates
public TemplateBase LoadTemplate(FileName fileName)
{
var fileSystem = SD.FileSystem;
using (TextReader reader = fileSystem.OpenText(fileName)) {
return LoadTemplate(reader, new ReadOnlyChrootFileSystem(fileSystem, fileName.GetParentDirectory()));
using (Stream stream = fileSystem.OpenRead(fileName)) {
return LoadTemplate(stream, new ReadOnlyChrootFileSystem(fileSystem, fileName.GetParentDirectory()));
}
}
public TemplateBase LoadTemplate(TextReader textReader, IReadOnlyFileSystem fileSystem)
public TemplateBase LoadTemplate(Stream stream, IReadOnlyFileSystem fileSystem)
{
try {
throw new NotImplementedException();
XmlDocument doc = new XmlDocument();
doc.Load(stream);
if (doc.DocumentElement["Files"] != null)
throw new NotImplementedException();
else if (doc.DocumentElement["Project"] != null || doc.DocumentElement["Solution"] != null)
return new ProjectTemplateImpl(doc, fileSystem);
else
throw new TemplateLoadException("Unknown file format");
} catch (XmlException ex) {
throw new TemplateLoadException(ex.Message, ex);
}

26
src/Setup/Files.wxs

@ -1024,14 +1024,6 @@ @@ -1024,14 +1024,6 @@
<Component Guid="810CE373-569B-41C3-ADDA-D2F0E0EFD5DE" Id="FSharpBindingDll" DiskId="1">
<File Source="..\..\AddIns\BackendBindings\FSharpBinding\FSharpBinding.dll" Name="FSharpBinding.dll" Id="FSharpBinding.dll" KeyPath="yes" Assembly=".net" AssemblyApplication="FSharpBinding.dll" AssemblyManifest="FSharpBinding.dll" />
</Component>
<Directory Id="FSharpBindingTemplates" Name="Templates">
<Component Guid="37A7695A-BA60-45A6-9BDB-FAE663D7A4C0" Id="FSharpConsoleProjectTemplate" DiskId="1">
<File Source="..\..\AddIns\BackendBindings\FSharpBinding\Templates\ConsoleProject.xpt" Name="ConsoleProject.xpt" Id="FSharp.Templates.ConsoleProject.xpt" KeyPath="yes" />
</Component>
<Component Guid="33142421-A648-4415-8C22-0F73479E0840" Id="FSharpEmptyClassTemplate" DiskId="1">
<File Source="..\..\AddIns\BackendBindings\FSharpBinding\Templates\EmptyClass.xft" Name="EmptyClass.xft" Id="FSharp.Templates.EmptyClass.xft" KeyPath="yes" />
</Component>
</Directory>
</Directory>
<!--
<Directory Id="RubyBinding" Name="RubyBinding">
@ -1134,16 +1126,6 @@ @@ -1134,16 +1126,6 @@
<Component Guid="AC3EFDF3-3063-464A-9072-1285BAAD3579" Id="CppBindingDll" DiskId="1">
<File Source="..\..\AddIns\BackendBindings\CppBinding\CppBinding.dll" Name="CppBinding.dll" Id="CppBinding.dll" KeyPath="yes" />
</Component>
<Directory Id="CppTemplates" Name="Templates">
<Component Guid="CD1E49C5-7037-46B0-81CE-41C3E10759E6" Id="CppBindingTemplates" DiskId="1">
<File Source="..\..\AddIns\BackendBindings\CppBinding\Templates\ConsoleProject.xpt" Name="ConsoleProject.xpt" Id="ConsoleProject.xpt" KeyPath="yes" />
<File Source="..\..\AddIns\BackendBindings\CppBinding\Templates\DefaultAssemblyInfo.cpp" Name="DefaultAssemblyInfo.cpp" Id="DefaultAssemblyInfo.cpp" />
<File Source="..\..\AddIns\BackendBindings\CppBinding\Templates\Empty.xft" Name="Empty.xft" Id="Templates.Empty1.xft" />
<File Source="..\..\AddIns\BackendBindings\CppBinding\Templates\EmptyClass.xft" Name="EmptyClass.xft" Id="Templates.EmptyClass1.xft" />
<File Source="..\..\AddIns\BackendBindings\CppBinding\Templates\Library.xpt" Name="Library.xpt" Id="Templates.Library.xpt" />
<File Source="..\..\AddIns\BackendBindings\CppBinding\Templates\UnmanagedConsoleProject.xpt" Name="UnmanagedConsoleProject.xpt" Id="UnmanagedConsoleProject.xpt" />
</Component>
</Directory>
</Directory>
<Directory Id="AspNet.Mvc" Name="AspNet.Mvc">
<Component Id="AspNetMvcAddin" Guid="2ADAB116-3E40-4A12-B6CD-EE41C482807A" DiskId="1">
@ -1381,19 +1363,11 @@ @@ -1381,19 +1363,11 @@
<Component Guid="31400415-BB2A-49C9-90DF-58F7FD0A8154" Id="ICSharpCodeDataSQLServerDll" DiskId="1">
<File Source="..\..\AddIns\DisplayBindings\Data\ICSharpCode.Data.SQLServer.dll" Name="ICSharpCode.Data.SQLServer.dll" Id="ICSharpCode.Data.SQLServer.dll" KeyPath="yes" />
</Component>
<Directory Id="DataTemplates" Name="Templates">
<Directory Id="Files" Name="Files">
<Component Guid="2791081B-A45D-4729-952C-43C147753653" Id="CSharpEDMXXft" DiskId="1">
<File Source="..\..\AddIns\DisplayBindings\Data\Templates\Files\CSharp.EDMX.xft" Name="CSharp.EDMX.xft" Id="CSharp.EDMX.xft" KeyPath="yes" />
</Component>
</Directory>
</Directory>
</Directory>
<Directory Id="SettingsEditor" Name="SettingsEditor">
<Component Id="SettingsEditorFiles" Guid="4A12129A-6BB5-4CC7-A105-C1F6FDF345F2" DiskId="1">
<File Id="SettingsEditor.dll" Name="SettingsEditor.dll" Source="..\..\AddIns\DisplayBindings\SettingsEditor\SettingsEditor.dll" KeyPath="yes" />
<File Id="SettingsEditor.addin" Name="SettingsEditor.addin" Source="..\..\AddIns\DisplayBindings\SettingsEditor\SettingsEditor.addin" />
<File Id="EmptySettingsFile.xft" Name="EmptySettingsFile.xft" Source="..\..\AddIns\DisplayBindings\SettingsEditor\EmptySettingsFile.xft" />
</Component>
</Directory>
<Directory Id="Decompiler" Name="Decompiler">

4
src/Setup/Setup.wxs

@ -399,8 +399,6 @@ @@ -399,8 +399,6 @@
<ComponentRef Id="FSharpBindingDll"/>
<ComponentRef Id="FSharpBindingAddin"/>
<ComponentRef Id="FSharpConsoleProjectTemplate"/>
<ComponentRef Id="FSharpEmptyClassTemplate"/>
<ComponentRef Id="SharpDevelopSourceAnalysisTargets"/>
<ComponentRef Id="SourceAnalysisAddin"/>
@ -423,7 +421,6 @@ @@ -423,7 +421,6 @@
<ComponentRef Id="CppBindingAddin"/>
<ComponentRef Id="CppBindingDll"/>
<ComponentRef Id="CppBindingTemplates"/>
<ComponentRef Id="ICSharpCodeWpfDesignAddInDll"/>
<ComponentRef Id="ICSharpCodeWpfDesignDesignerDll"/>
@ -438,7 +435,6 @@ @@ -438,7 +435,6 @@
<ComponentRef Id="ICSharpCodeDataEDMDesignerCoreDll"/>
<ComponentRef Id="ICSharpCodeDataEDMDesignerCoreUIDll"/>
<ComponentRef Id="ICSharpCodeDataSQLServerDll"/>
<ComponentRef Id="CSharpEDMXXft"/>
<ComponentRef Id="UDCSystemDataSQLiteDll"/>
<ComponentRef Id="UsageDataCollectorAddin"/>

Loading…
Cancel
Save